vis

@bzoj - 1921@ [ctsc2010]珠宝商

☆樱花仙子☆ 提交于 2020-01-21 09:44:31
目录 @description@ @solution@ @accepted code@ @details@ @description@ 简述版题意:给定字符串 S 与一棵树 T,树上每个点有一个字符。求树上所有简单路径对应的字符串在 S 中的出现次数之和。 原题链接。 @solution@ 一个显然的暴力:O(N^2) 枚举所有点对的字符串,建后缀自动机跑算出现次数之和。 另一个看起来比较好的算法:点分治。 每次计算经过重心的字符串,可以拆成两部分:某个点到重心的字符串 + 重心到某个点的字符串。 不过合并的时候需要在原字符串 S 上找分界点(不然无法合并),该算法执行一次复杂度为 O(M)。 接下来?发现并没有什么更好的性质可以利用。 数据范围比较小,我们不妨考虑一些玄学的操作:平衡复杂度。 在点分治时,如果当前连通块大小 < \(\sqrt{M}\) 则执行第一种暴力,否则执行第二种暴力。这样平衡下来复杂度为 \(O(N\sqrt{M})\) 。 看起来比较显然:连通块大小 < \(\sqrt{M}\) 时 O(size^2) 优于 O(M);否则 O(M) 优于 O(size^2)。 至于复杂度的正确性,第一种暴力的总和显然 \(O(N\sqrt{M})\) 。第二种暴力由于决策树的叶子个数 <= \(O(\sqrt{M})\) ,而深度为 logN(点分治),所以也是 \

最短路(Dijkstra,Floyd,Bellman_Ford,SPFA)

|▌冷眼眸甩不掉的悲伤 提交于 2020-01-20 21:45:05
当然,这篇文章是借鉴大佬的。。。 最短路算法大约来说就是有4种——Dijkstra,Floyd,Bellman_Ford,SPFA 接下来,就可以一一看一下。。。 1. Dijkstra (权值非负,适用于有向图及无向图,单源最短路) 1 Dijkstra's算法解决的是图中单个源点到其它顶点的最短路径。只能解决权值非负(看了代码就知道了) 2 Dijkstral只能求出任意点到达源点的最短距离(不能求出任意两点之间的最短距离),同时适用于有向图和无向图,复杂度为O(n^2). 3算法的过程: 1设置顶点集合S并不断的作贪心选择来选择扩充这个集合。一个顶点属于集合S当且仅当从源点到该点的最短路径长度已知 2 初始时,S中仅含有源。设U是G的某一个顶点,把从源到U且中间只经过S中的顶点的路称为从源到U的特殊路径,并用dis数组距离当前每一个顶点所对应的最短特殊路径 3Dijkstra算法每一次从V-S中取出具有最短特殊长度的顶点u,将u添加到S中,同时对dis数组进行修改。一旦S包含了所有的V中的顶点,dis数组就记录了从源点到其它顶点的最短路径长度。 4 模板: 没有优化,时间复杂度o(n^2) 1 #define MAXN 1010 2 #define INF 0xFFFFFFF 3 int value[MAXN][MAXN];/*保存的是边权值*/ 4 int dis[MAXN

Educational Codeforces Round 80 D. Minimax Problem

∥☆過路亽.° 提交于 2020-01-20 20:51:37
http://codeforces.com/contest/1288/problem/D 题意: 给出一张n*m的表a[n][m],m<=8,从中任选两行i,j 令b[k]=max(a[i][k],a[j]k]) 最大化 min(b[k]) 二分答案x 若a[i][j]>=x,令c[i][j]=1,否则c[i][j]=0 若最终答案>=x,则存在i,j,满足c中第i行和第j行 按位或 的结果都是1 枚举行肯定超时 m<=8,每一行的01状态不超过256种,所以可以枚举行的01状态 可以用bitset做 #include<cmath> #include<cstdio> #include<bitset> #include<cstring> #include<iostream> using namespace std; #define N 300001 int n,m,a[N][8]; bitset<8>b[N]; int vis[256]; int use[256][256],siz[256]; int all; int turn[N]; bool check(int x) { memset(vis,0,sizeof(vis)); for(int i=1;i<=n;++i) { b[i].reset(); for(int j=0;j<m;++j) if(a[i][j]>=x) b[i]

Codeforces Round #614 (Div. 2)

陌路散爱 提交于 2020-01-20 05:50:10
21:35刚刚降落广州白云机场,在手机上打了个Python刷个场次,顺便掉个蓝色献祭一下这个学期的考试分数。 A - ConneR and the A.R.C. Markland-N 题意:找不出现在k个给定数字之中的,值域在[1,n]的离s最近的数字的距离。保证k<n。 题解: 1.常数比较低的做法:先排序,然后看看s是不是在k个数字里面,不在的话直接就0,否则一定在里面。然后给ans赋值初始值,取k个数字的两端。然后遍历每个数字,只要它和上一个数字不连续,那么中间可以贪心一个位置(然后break掉,但是懒)。 int a[1005]; void test_case() { int n, s, k; scanf("%d%d%d", &n, &s, &k); for(int i = 1; i <= k; ++i) scanf("%d", &a[i]); sort(a + 1, a + 1 + k); int pos = 0; for(int i = 1; i <= k; ++i) { if(a[i] == s) { pos = i; break; } } if(pos == 0) { puts("0"); return; } int ans = INF; if(a[1] != 1) ans = s - (a[1] - 1); if(a[k] != n) ans = min(ans,

wenbao与动态规划

守給你的承諾、 提交于 2020-01-20 04:05:30
终于要开始了。。。。。。。。 万能的dp ------------------------------------------------------------------------------------------------------------------------------------------------------------------ 动规入门级题目 数字三角形 不多说 http://lx.lanqiao.cn/problem.page?gpid=T312 1 #include <iostream> 2 using namespace std; 3 int a[105][105]; 4 int main(){ 5 int n; 6 scanf("%d", &n); 7 for(int i = 0; i < n; ++i){ 8 for(int j = 0; j <= i; ++j){ 9 scanf("%d", &a[i][j]); 10 } 11 } 12 for(int i = n-2; i >= 0; --i){ 13 for(int j = 0; j <= i; ++j){ 14 a[i][j] = a[i][j] + max(a[i+1][j], a[i+1][j+1]); 15 //cout<<i<<" "<<j<<" "<<a[i][j]

洛谷P2024 食物链

时间秒杀一切 提交于 2020-01-19 20:23:28
链接 这应该是并查集挺难的题目了然后我上课听老师讲的听清楚,我就心想: 这么简单的题我要切了他!! 于是我按照自己记录的思路写了一下午就成了这个样子 对不起,是我太菜了 于是呢我就去看了题解,整个修改代码的难点在于我思路和题解完全不一样??? 正确思路: 链接 重点在于正确构造出要求的形式,前提是能看出来这个用并查集 // // main.cpp // P2024 // // Created by 曹宇琮 on 2020/1/19. // Copyright © 2020 曹宇琮. All rights reserved. // //#include <iostream> //#include <cstdio> //#include <algorithm> //#include <cstdio> //#include <cstring> //using namespace std; //int n,k;int fa[150099],dep[150099],vis[150099]; //int cnt = 0; // //int getfa(int x){ // return fa[x] == x ? x : getfa(fa[x]); //} // //void add_point(int x,int y,int tmp){//把x合并到y的集合中 // int was = vis

最短路算法总结

送分小仙女□ 提交于 2020-01-19 17:08:30
最短路径问题 前言 最短路问题(short-path problem)是网络理论解决的典型问题之一,可用来解决管路铺设、线路安装、厂区布局和设备更新等实际问题。基本内容是:若网络中的每条边都有一个数值(长度、成本、时间等),则找出两节点(通常是源节点和阱节点)之间总权和最小的路径就是最短路问题。 存储方式 1.邻接矩阵 2.邻接表 3.链式前向星 无向图 视为正反的 有向图 叠加 算法 一般常用4种方法解决 1.Dijkstra算法 O(N^2) 2.Floyd算法 O(N^3) 3.Bellman-Ford算法 O(NM) 4.SPFA算法 O(NM) 其中由 Bellman-Ford算法衍生出SPFA算法 实质就是 队列优化的 Bellman-Ford 它们具体的原理和实现如下 1. Dijkstra 算法 适用问题 单源最短路径 (一个源点出发) 适用范围 没有负边权 没有负环的图 实现步骤 1.初始化dis[起点]=0 其余节点为无穷大 2.找出未被标记且dis[x]最小的x 再标记x 3.扫描x所有出边(x,y, edge(x,y) )dis[y]=min(dis[y],dis[x]+edge(x,y)) 4.重复2-3到所有节点均被标记 总结:贪心思想 不满足负边( 与贪心思想相矛盾 ) 模板题目 题目描述 输入一个无向网络,输出其中2个顶点之间的最短路径长度 输入

【模板】SPFA最短路

妖精的绣舞 提交于 2020-01-19 16:11:46
#include<bits/stdc++.h> #define maxn 10005 using namespace std; int n,m,s; vector<int> v[maxn],w[maxn]; int dis[maxn]; bool vis[maxn]; void SPFA() { memset(dis,0x3f3f3f3f,sizeof(dis)); queue<int> q; dis[s]=0; vis[s]=1; q.push(s); while(!q.empty()) { int x=q.front(); q.pop(); vis[x]=false;//vis标记是否在队列里 for(int i=0;i<v[x].size();i++) { int y=v[x][i]; if(dis[x]+w[x][i]<dis[y]) { dis[y]=dis[x]+w[x][i]; if(!vis[y]) { vis[y]=true; q.push(y); } } } } } int main() { scanf("%d%d%d",&n,&m,&s); for(int i=1;i<=m;i++) { int x,y,val; scanf("%d%d%d",&x,&y,&val); v[x].push_back(y); w[x].push_back(val); } SPFA

图论四:最短路径算法

爷,独闯天下 提交于 2020-01-19 15:25:55
一、广度优先搜索 1、思路:距离开始点最近的点首先被赋值,最远的点最后被赋值。 2、适用范围:对于非负数权的无圈图来说(单源最短路径)。 3、算法实现: (1)一个队列记录每个每个节点的编号。 (2)将起始节点入队,将所有节点到起始节点的距离设置为无穷大,起始节点到起始节点的距离为0; (3)取队列的第一个节点,这个节点出队,遍历这个节点相邻的节点,如果这个节点的距离是INF就变为它前一个节点的距离+1,并且入队。 (4)重复(3)操作,直到所有所有队列为空为止,此时dis数组记录了每一个节点到起始节点的最小距离。 4、代码: #include<iostream> #include<cstdio> #include<queue> #include<vector> using namespace std; const int maxn = 1200; const int INF = 0x3fff; vector <int> vc[maxn]; int dis[maxn]; void bfs(int n) { int i,j,tmp; for(i=1;i<=n;i++) dis[i]=INF; dis[1]=0; queue <int> q; q.push(1); while(!q.empty()) { tmp=q.front(); q.pop(); for(i=0;i<vc[tmp]

最短路

左心房为你撑大大i 提交于 2020-01-19 15:24:42
  最短路是图论的基础部分。其中学过4个主要算法,分别是Floyed,Dijkstra,Ford,SPFA。SPFA作为Ford的队列实现,有一定的优化,因此就不说Ford了。   首先两点间距离读取都是一样的。 memset(f,0x3f,sizeof(f)); for(int i=1;i<=n;++i) f[i][i]=0; for(int i=1;i<=e;++i) { scanf("%d%d%d",&a,&b,&distance); f[a][b]=distance; f[b][a]=distance; }   Floyed。特点是解决了所有点的最短路,且试用于负边权的情况。但时间复杂度是O(n^3),所以一般用处不大。 #define FOR(i,x,y) for(int i=x;i<=y;++i) #define MIN(a,b) a<b?a:b FOR(k,1,n) FOR(i,1,n) FOR(j,1,n) f[i][j]=MIN(f[i][j],f[i][k]+f[k][j]);   Dijkstra。特点是计算了单点间最短路,不能在负边权的时候使用。时间复杂度O(n^2),可以考虑使用。 int Dijkstra(int st,int en) { memset(vis,0,sizeof(vis)); FOR(i,1,n) ans[i]=f[st][i]; FOR