二分图判定
1 #include <cstdio> 2 #include <vector> 3 using namespace std; 4 5 const int MAX_V=10000; 6 vector<int> G[MAX_V];//邻接表存图 7 int V,E; 8 int color[MAX_V];//顶点的颜色1或-1 9 10 bool dfs(int, int);//把顶点染成1或-1 11 12 int main() 13 { 14 scanf("%d %d", &V, &E); 15 for (int i=0; i<E; i++) 16 { 17 int s,t; 18 scanf("%d %d", &s, &t); 19 G[s].push_back(t); 20 G[t].push_back(s); 21 } 22 for (int i=0; i<V; i++) 23 { 24 if (color[i]==0) 25 { 26 if (!dfs(i,1))//如果顶点还没被染色,则染成1 27 { 28 printf("No\n"); 29 return 0; 30 } 31 } 32 } 33 printf("Yes\n"); 34 return 0; 35 } 36 37 bool dfs(int v, int c) 38 { 39 color[v]=c;//把顶点v染成颜色c 40 for (int i=0; i<G[v].size(); i++) 41 { 42 //如果相邻顶点同色,则返回false 43 if (color[G[v][i]]==c) return false; 44 //如果相邻顶点还没被染色,则染成-c 45 if (color[G[v][i]]==0 && !dfs(G[v][i],-c)) return false;// 46 } 47 //如果所有顶点都染过色了,则返回true 48 return true; 49 }
最短路问题
单源最短路问题1(Bellman-Ford算法)
1 #include <cstdio> 2 #include <vector> 3 using namespace std; 4 5 struct edge 6 { 7 int from, to, cost; 8 }; 9 const int INF=0x3ffffff; 10 const int MAX_E=10000; 11 const int MAX_V=10000; 12 edge es[MAX_E]; 13 int d[MAX_V]; 14 int V,E,s; 15 16 int main() 17 { 18 scanf("%d %d %d", &V, &E, &s); 19 for (int i=0; i<E; i++) 20 { 21 scanf("%d %d %d", &es[i].from, &es[i].to, &es[i].cost); 22 } 23 for (int i=0; i<V; i++) d[i]=INF; 24 d[s]=0; 25 while (true) 26 { 27 bool update=false; 28 for (int i=0; i<E; i++) 29 { 30 edge e=es[i]; 31 if (d[e.from]!=INF && d[e.from]+e.cost<d[e.to]) 32 { 33 d[e.to]=d[e.from]+e.cost; 34 update=true; 35 } 36 } 37 if (!update) break; 38 } 39 for (int i=0; i<V; i++) printf("%d ", d[i]); 40 }
如果在图中不存在从s可达的负圈,那么最短路不会经过同一个顶点两次(也就是说最多通过|V|-1条边),while(true)的循环最多执行|V|-1次,因此,复杂度是O(|V|*|E|)。反之,如果存在从s可达的负圈,那么在第|V|次循环中也会更新d的值,因此也可以用这个性质来检查负圈。如果一开始对所有的顶点都把d[i]初始化为0,那么可以检查出所有的负圈,这部分代码如下:
1 #include <cstdio> 2 #include <vector> 3 #include <cstring> 4 5 using namespace std; 6 7 struct edge 8 { 9 int from, to, cost; 10 }; 11 const int INF=0x3ffffff; 12 const int MAX_E=10000; 13 const int MAX_V=10000; 14 edge es[MAX_E]; 15 int d[MAX_V]; 16 int V,E,s; 17 bool find_negative_loop(); 18 19 int main() 20 { 21 scanf("%d %d %d", &V, &E, &s); 22 for (int i=0; i<E; i++) 23 { 24 scanf("%d %d %d", &es[i].from, &es[i].to, &es[i].cost); 25 } 26 if (find_negative_loop()) printf("Exist negative loop!"); 27 else printf("No negative loop."); 28 } 29 30 bool find_negative_loop() 31 { 32 memset(d,0,sizeof(d)); 33 for (int i=0; i<V; i++) 34 { 35 for (int j=0; j<E; j++) 36 { 37 edge e=es[j]; 38 if (d[e.to]>d[e.from]+e.cost) 39 { 40 d[e.to]=d[e.from]+e.cost; 41 if (i==V-1) return true; 42 } 43 } 44 } 45 return false; 46 }
1 #include <cstdio> 2 #include <cstring> 3 #include <queue> 4 5 using namespace std; 6 7 struct edge 8 { 9 int to; 10 int cost; 11 }; 12 const int INF=0x3f3f3f3f; 13 const int MAX_V=100000; 14 const int MAX_E=200000; 15 int d[MAX_V]; 16 int inque[MAX_V]; 17 vector<edge> G[MAX_V]; 18 int V,E,s; 19 void spfa(int); 20 queue<int> que; 21 22 int main() 23 { 24 scanf("%d %d %d", &V, &E, &s); 25 --s; 26 for (int i=0; i<E; i++) 27 { 28 edge e; 29 int s,t,c; 30 scanf("%d %d %d", &s, &t, &c); 31 e.to=t-1;e.cost=c; 32 G[s-1].push_back(e); 33 } 34 spfa(s); 35 for (int i=0; i<V; i++) 36 { 37 if (d[i]!=INF) printf("%d ", d[i]); 38 else printf("%d ", 2147483647); 39 } 40 } 41 42 void spfa(int s) 43 { 44 memset(d,0x3f,sizeof(d));//0x3f3f3f3f是一个非常棒的无穷大的选择! 45 d[s]=0; 46 while(!que.empty()) que.pop(); 47 que.push(s); 48 inque[s]=true; 49 while (!que.empty()) 50 { 51 int u=que.front(); 52 que.pop(); 53 inque[u]=false; 54 for (int i=0; i<G[u].size(); i++) 55 if (d[u]+G[u][i].cost<d[G[u][i].to]) 56 { 57 d[G[u][i].to]=d[u]+G[u][i].cost; 58 if (!inque[G[u][i].to]) 59 { 60 inque[G[u][i].to]=true; 61 que.push(G[u][i].to); 62 } 63 } 64 } 65 }
单源最短路问题2(Dijkstra算法)
1 #include <cstdio> 2 #include <vector> 3 #include <algorithm> 4 5 using namespace std; 6 7 struct edge 8 { 9 int to; 10 int cost; 11 }; 12 13 const int MAX_V=100000; 14 const int MAX_E=200000; 15 const int INF=0x3f3f3f3f; 16 vector<edge> G[MAX_V]; 17 int V,E,S; 18 int d[MAX_V]; 19 bool used[MAX_V]; 20 21 void dijkstra(int); 22 23 int main() 24 { 25 scanf("%d %d %d", &V, &E, &S); 26 --S; 27 for (int i=0; i<E; i++) 28 { 29 int s,t,c; 30 scanf("%d %d %d", &s, &t, &c); 31 edge e; 32 e.to=t-1;e.cost=c; 33 G[s-1].push_back(e); 34 } 35 dijkstra(S); 36 for (int i=0; i<V; i++) 37 if (d[i]!=INF) printf("%d ", d[i]); 38 else printf("%d ", 2147483647); 39 } 40 41 void dijkstra(int s) 42 { 43 fill(d, d+V, INF); 44 fill(used, used+V, false); 45 d[s]=0; 46 while (true) 47 { 48 int v=-1; 49 for (int u=0; u<V; u++) 50 if (!used[u] && (v==-1 || d[u]<d[v])) v=u; 51 if (v==-1) break; 52 used[v]=true; 53 for (int i=0; i<G[v].size(); i++) 54 if (d[G[v][i].to]>d[v]+G[v][i].cost) 55 d[G[v][i].to]=d[v]+G[v][i].cost; 56 } 57 }
Dijkstra算法的复杂度是O(|V|2),大部分的时间花在了查找下一个使用的顶点上,因此需要使用合适的数据结构对其进行优化
1 #include <cstdio> 2 #include <vector> 3 #include <algorithm> 4 #include <functional> 5 #include <queue> 6 7 using namespace std; 8 9 struct edge 10 { 11 int to; 12 int cost; 13 }; 14 15 typedef pair<int, int> P; 16 17 const int MAX_V=100000; 18 const int MAX_E=200000; 19 const int INF=0x3f3f3f3f; 20 vector<edge> G[MAX_V]; 21 int V,E,S; 22 int d[MAX_V]; 23 24 void dijkstra(int); 25 26 int main() 27 { 28 scanf("%d %d %d", &V, &E, &S); 29 --S; 30 for (int i=0; i<E; i++) 31 { 32 int s,t,c; 33 scanf("%d %d %d", &s, &t, &c); 34 edge e; 35 e.to=t-1;e.cost=c; 36 G[s-1].push_back(e); 37 } 38 dijkstra(S); 39 for (int i=0; i<V; i++) 40 if (d[i]!=INF) printf("%d ", d[i]); 41 else printf("%d ", 2147483647); 42 } 43 44 void dijkstra(int s) 45 { 46 fill(d, d+V, INF); 47 d[s]=0; 48 priority_queue<P, vector<P>, greater<P> > que; 49 que.push(P(0,s)); 50 while (!que.empty()) 51 { 52 P p=que.top();que.pop(); 53 int v=p.second; 54 if (d[v]<p.first) continue; 55 for (int i=0; i<G[v].size(); i++) 56 { 57 edge e=G[v][i]; 58 if (d[e.to]>d[v]+e.cost) 59 { 60 d[e.to]=d[v]+e.cost; 61 que.push(P(d[e.to], e.to)); 62 } 63 } 64 } 65 }
任意两点间的最短路问题(Floyd-Warshall算法)
求解所有两点间的最短路的问题。
用DP求解:只使用顶点0~k和i,j的情况下,记i到j的最短路长度为d[k][i][j]。
当k=-1时,认为只使用i和j,所以d[-1][i][[j]=cost[i][j]。
接下来把只使用顶点0~k的问题规约到只使用0~k-1的问题上:只使用0~k时,我们分i到j的最短路正好经过顶点k一次和完全不经过顶点k两种情况来讨论。①不经过顶点k的情况下,d[k][i][j]=d[k-1][i][j],②通过顶点k的情况下,d[k][i][j]=d[k-1][i][k]+d[k-1][k][j]。
合起来,就得到了d[k][i][j]=min(d[k-1][i][j],d[k-1][i][k]+d[k-1][k][j])。显然,这个DP也可以使用二维数组不断进行d[i][j]=min(d[i][j],d[i][k]+d[k][j])的更新来实现
这就是Floyd-Warshall算法,复杂度O(|V|3),可以处理边是负数的情况。判断图中是否有负圈只需检查是否存在d[i][i]是负数的顶点i就可以了。
1 #include <cstdio> 2 #include <cstring> 3 4 using namespace std; 5 6 const int INF=0x3f3f3f3f; 7 int V,E,S; 8 int **d; 9 10 void floyd(); 11 int min(int, int); 12 13 int main() 14 { 15 scanf("%d %d %d", &V, &E, &S); 16 --S; 17 d=new int*[V]; 18 for (int i=0; i<=V; i++) 19 { 20 d[i]=new int[V]; 21 memset(d[i],0x3f,sizeof(int)*(V)); 22 } 23 for (int i=0; i<E; i++) 24 { 25 int s,t,c; 26 scanf("%d %d %d", &s, &t, &c); 27 d[s-1][t-1]=min(d[s-1][t-1],c); 28 } 29 for (int i=0; i<V; i++) d[i][i]=0; 30 floyd(); 31 for (int i=0; i<V; i++) 32 if (d[S][i]!=INF) printf("%d ", d[S][i]); 33 else printf("%d ", 2147483647); 34 } 35 36 int min(int x, int y) 37 { 38 if (x<y) return x; 39 return y; 40 } 41 42 void floyd() 43 { 44 for (int k=0; k<V; k++) 45 { 46 for (int i=0; i<V; i++) 47 { 48 for (int j=0; j<V; j++) 49 { 50 d[i][j] = min(d[i][j],d[i][k]+d[k][j]); 51 } 52 } 53 } 54 }
路径还原
当需要求解最短路的路径时,不断寻找前趋节点就可以恢复出最短路。用prev[j]来记录最短路上顶点j的前趋,呢么就可以在O(|V|)的时间内完成最短路的恢复。在d[j]被d[j]=d[k]+cost[k][j]更新时,修改prev[j]=k,这样就可以得到prev数组,在计算从s出发到j的最短路时,通过prev[j]就可以知道顶点j的前趋,因此不断把j替换成prev[j]直到j=s为止就可以了。
1 vector<int> get_path(int t) 2 { 3 vector<int> path; 4 for (; t!=-1; t=prev[t]) path.push_back(t);//path[]初始值全为-1 5 reverse(path.begin(),path.end()); 6 return path; 7 }
最小生成树(MST, Minimum Spanning Tree)【生成树是否存在和图是否连通是等价的】
最小生成树问题1(Prim算法)
1 #include <cstdio> 2 #include <queue> 3 #include <vector> 4 #include <functional> 5 #define num s-‘0‘ 6 7 using namespace std; 8 9 typedef pair<int, int> P; 10 struct edge 11 { 12 int to; 13 int cost; 14 }; 15 16 const int MAX_V=5000; 17 const int INF=0x3f3f3f3f; 18 int V,E,n; 19 vector<edge> G[MAX_V]; 20 int res; 21 int mincost[MAX_V]; 22 bool used[MAX_V]; 23 24 void prim(); 25 26 void read(int &x){ 27 char s; 28 x=0; 29 bool flag=0; 30 while(!isdigit(s=getchar())) 31 (s==‘-‘)&&(flag=true); 32 for(x=num;isdigit(s=getchar());x=x*10+num); 33 (flag)&&(x=-x); 34 } 35 36 void write(int x) 37 { 38 if(x<0) 39 { 40 putchar(‘-‘); 41 x=-x; 42 } 43 if(x>9) 44 write(x/10); 45 putchar(x%10+‘0‘); 46 } 47 48 int main() 49 { 50 read(V); 51 read(E); 52 for (int i=0; i<E; i++) 53 { 54 int s,t,c; 55 read(s);read(t);read(c); 56 edge e; 57 e.to=t-1;e.cost=c; 58 G[s-1].push_back(e); 59 e.to=s-1;e.cost=c; 60 G[t-1].push_back(e); 61 } 62 prim(); 63 if (n<V) puts("orz"); 64 else write(res); 65 putchar(‘\n‘); 66 } 67 68 void prim() 69 { 70 for (int i=0; i<V; i++) 71 { 72 mincost[i]=INF; 73 used[i]=false; 74 } 75 mincost[0]=0; 76 priority_queue<P, vector<P>, greater<P>> que; 77 que.push(P(0,0)); 78 while (!que.empty()) 79 { 80 P p=que.top(); que.pop(); 81 int v=p.second; 82 if (mincost[v]<p.first) continue; 83 res+=mincost[v];++n;used[v]=true; 84 for (int i=0; i<G[v].size(); i++) 85 { 86 if (mincost[G[v][i].to]>G[v][i].cost && !used[G[v][i].to]) 87 { 88 mincost[G[v][i].to]=G[v][i].cost; 89 que.push(P(G[v][i].cost,G[v][i].to)); 90 } 91 } 92 } 93 }
这段代码使用了读入优化和输出优化,并且在遇到图不连通的情况时输出orz
最小生成树问题2(Kruskal算法)
1 #include <cstdio> 2 #include <queue> 3 #include <vector> 4 #include <algorithm> 5 #include <cctype> 6 #define num s-‘0‘ 7 8 using namespace std; 9 10 struct edge 11 { 12 int u; 13 int v; 14 int cost; 15 }; 16 17 const int MAX_V=5000; 18 const int MAX_E=200000; 19 const int INF=0x3f3f3f3f; 20 int V,E,n; 21 edge es[MAX_E]; 22 int res; 23 int par[MAX_V]; 24 int r[MAX_V]; 25 26 void kruskal(); 27 void init(); 28 int find(int); 29 void unite(int, int); 30 bool same(int, int); 31 32 void read(int &x){ 33 char s; 34 x=0; 35 bool flag=0; 36 while(!isdigit(s=getchar())) 37 (s==‘-‘)&&(flag=true); 38 for(x=num;isdigit(s=getchar());x=x*10+num); 39 (flag)&&(x=-x); 40 } 41 42 void write(int x) 43 { 44 if(x<0) 45 { 46 putchar(‘-‘); 47 x=-x; 48 } 49 if(x>9) 50 write(x/10); 51 putchar(x%10+‘0‘); 52 } 53 54 bool compare(const edge &e1, const edge &e2) 55 { 56 return e1.cost<e2.cost; 57 } 58 59 int main() 60 { 61 read(V);read(E); 62 for (int i=0; i<E; i++) 63 { 64 read(es[i].u);read(es[i].v);read(es[i].cost); 65 es[i].u--;es[i].v--; 66 } 67 kruskal(); 68 write(res); 69 putchar(‘\n‘); 70 } 71 72 void init() 73 { 74 for (int i=0; i<V; i++) 75 { 76 par[i]=i; 77 r[i]=0; 78 } 79 } 80 81 int find(int x) 82 { 83 if (par[x]==x) return x; 84 return par[x]=find(par[x]); 85 } 86 87 void unite(int x, int y) 88 { 89 x=find(x); 90 y=find(y); 91 if (x==y) return; 92 if (r[x]<r[y]) par[x]=y; 93 else 94 { 95 par[y]=x; 96 if (r[x]==r[y]) r[x]++; 97 } 98 } 99 100 bool same(int x, int y) 101 { 102 return (find(x)==find(y)); 103 } 104 105 void kruskal() 106 { 107 sort(es, es+E, compare); 108 init(); 109 int n=0; 110 for (int i=0; i<E; i++) 111 { 112 edge e=es[i]; 113 if (!same(e.u, e.v)) 114 { 115 unite(e.u, e.v); 116 res+=e.cost; 117 ++n; 118 } 119 if (n==V-1) break; 120 } 121 }
Roadblocks(POJ 3255)
Time Limit: 2000MS | Memory Limit: 65536K |
Total Submissions: 19299 | Accepted: 6773 |
Description
Bessie has moved to a small farm and sometimes enjoys returning to visit one of her best friends. She does not want to get to her old home too quickly, because she likes the scenery along the way. She has decided to take the second-shortest rather than the shortest path. She knows there must be some second-shortest path.
The countryside consists of R (1 ≤ R ≤ 100,000) bidirectional roads, each linking two of the N (1 ≤ N ≤ 5000) intersections, conveniently numbered 1..N. Bessie starts at intersection 1, and her friend (the destination) is at intersection N.
The second-shortest path may share roads with any of the shortest paths, and it may backtrack i.e., use the same road or intersection more than once. The second-shortest path is the shortest path whose length is longer than the shortest path(s) (i.e., if two or more shortest paths exist, the second-shortest path is the one whose length is longer than those but no longer than any other path).
Input
Output
Sample Input
4 4 1 2 100 2 4 200 2 3 250 3 4 100
Sample Output
450
Hint
1 #include <cstdio> 2 #include <queue> 3 #include <vector> 4 #include <functional> 5 #include <cctype> 6 #include <algorithm> 7 #define num s-‘0‘ 8 9 using namespace std; 10 typedef pair<int, int> P; 11 12 struct edge 13 { 14 int to; 15 int cost; 16 }; 17 18 const int MAX_V=5000; 19 const int INF=0x3f3f3f3f; 20 int V,E,n; 21 vector<edge> G[MAX_V]; 22 int dist[MAX_V]; 23 int dist2[MAX_V]; 24 25 void solve(); 26 27 void swap(int &x, int &y) 28 { 29 int t=x; 30 x=y;y=t; 31 } 32 33 void read(int &x){ 34 char s; 35 x=0; 36 bool flag=0; 37 while(!isdigit(s=getchar())) 38 (s==‘-‘)&&(flag=true); 39 for(x=num;isdigit(s=getchar());x=x*10+num); 40 (flag)&&(x=-x); 41 } 42 43 void write(int x) 44 { 45 if(x<0) 46 { 47 putchar(‘-‘); 48 x=-x; 49 } 50 if(x>9) 51 write(x/10); 52 putchar(x%10+‘0‘); 53 } 54 55 int main() 56 { 57 read(V);read(E); 58 for (int i=0; i<E; i++) 59 { 60 edge e; 61 int s,t,c; 62 read(s);read(t);read(c); 63 e.to=t-1;e.cost=c; 64 G[s-1].push_back(e); 65 e.to=s-1;e.cost=c; 66 G[t-1].push_back(e); 67 } 68 solve(); 69 write(dist2[V-1]); 70 putchar(‘\n‘); 71 } 72 73 void solve() 74 { 75 priority_queue<P, vector<P>, greater<P> > que; 76 fill(dist, dist+V, INF); 77 fill(dist2, dist2+V, INF); 78 dist[0]=0; 79 que.push(P(0,0)); 80 while (!que.empty()) 81 { 82 P p=que.top(); que.pop(); 83 int v=p.second, d=p.first; 84 if (dist2[v]<d) continue; 85 for (int i=0; i<G[v].size(); i++) 86 { 87 edge &e=G[v][i]; 88 int d2=d+e.cost; 89 if (dist[e.to]>d2) 90 { 91 swap(dist[e.to],d2); 92 que.push(P(dist[e.to],e.to)); 93 } 94 if (dist2[e.to]>d2 && dist[e.to]<d2) 95 { 96 dist2[e.to]=d2; 97 que.push(P(dist2[e.to],e.to)); 98 } 99 } 100 } 101 }
Conscription(POJ 3723)
Time Limit: 1000MS | Memory Limit: 65536K |
Total Submissions: 16578 | Accepted: 5762 |
Description
Windy has a country, and he wants to build an army to protect his country. He has picked up N girls and M boys and wants to collect them to be his soldiers. To collect a soldier without any privilege, he must pay 10000 RMB. There are some relationships between girls and boys and Windy can use these relationships to reduce his cost. If girl x and boy y have a relationship d and one of them has been collected, Windy can collect the other one with 10000-d RMB. Now given all the relationships between girls and boys, your assignment is to find the least amount of money Windy has to pay. Notice that only one relationship can be used when collecting one soldier.
Input
The first line of input is the number of test case.
The first line of each test case contains three integers, N, M and R.
Then R lines followed, each contains three integers xi, yi and di.
There is a blank line before each test case.
1 ≤ N, M ≤ 10000
0 ≤ R ≤ 50,000
0 ≤ xi < N
0 ≤ yi < M
0 < di < 10000
Output
Sample Input
2 5 5 8 4 3 6831 1 3 4583 0 0 6592 0 1 3063 3 3 4975 1 3 2049 4 2 2104 2 2 781 5 5 10 2 4 9820 3 2 6236 3 1 8864 2 4 8326 2 0 5156 2 0 1463 4 1 2439 0 4 4373 3 4 8889 2 4 3133
Sample Output
71071 54223
1 #include <cstdio> 2 #include <queue> 3 #include <vector> 4 #include <algorithm> 5 #include <cctype> 6 #define num s-‘0‘ 7 8 using namespace std; 9 10 struct edge 11 { 12 int u; 13 int v; 14 int cost; 15 }; 16 17 const int MAX_V=30000; 18 const int MAX_E=60000; 19 const int INF=0x3f3f3f3f; 20 int K,N, M, E, V; 21 edge es[MAX_E]; 22 long long res; 23 int par[MAX_V]; 24 int r[MAX_V]; 25 26 void kruskal(); 27 void init(); 28 int find(int); 29 void unite(int, int); 30 bool same(int, int); 31 32 void read(int &x){ 33 char s; 34 x=0; 35 bool flag=0; 36 while(!isdigit(s=getchar())) 37 (s==‘-‘)&&(flag=true); 38 for(x=num;isdigit(s=getchar());x=x*10+num); 39 (flag)&&(x=-x); 40 } 41 42 void write(int x) 43 { 44 if(x<0) 45 { 46 putchar(‘-‘); 47 x=-x; 48 } 49 if(x>9) 50 write(x/10); 51 putchar(x%10+‘0‘); 52 } 53 54 bool compare(const edge &e1, const edge &e2) 55 { 56 return e1.cost<e2.cost; 57 } 58 59 int main() 60 { 61 read(K); 62 for (int j=0; j<K; j++) 63 { 64 res=0; 65 read(N);read(M);read(E);V=N+M; 66 for (int i=0; i<E; i++) 67 { 68 read(es[i].u);read(es[i].v);read(es[i].cost); 69 es[i].v+=N;es[i].cost=-es[i].cost; 70 } 71 kruskal(); 72 write(10000*(N+M)+res); 73 putchar(‘\n‘); 74 } 75 } 76 77 void init() 78 { 79 for (int i=0; i<V; i++) 80 { 81 par[i]=i; 82 r[i]=0; 83 } 84 } 85 86 int find(int x) 87 { 88 if (par[x]==x) return x; 89 return par[x]=find(par[x]); 90 } 91 92 void unite(int x, int y) 93 { 94 x=find(x); 95 y=find(y); 96 if (x==y) return; 97 if (r[x]<r[y]) par[x]=y; 98 else 99 { 100 par[y]=x; 101 if (r[x]==r[y]) r[x]++; 102 } 103 } 104 105 bool same(int x, int y) 106 { 107 return (find(x)==find(y)); 108 } 109 110 void kruskal() 111 { 112 sort(es, es+E, compare); 113 init(); 114 for (int i=0; i<E; i++) 115 { 116 edge e=es[i]; 117 if (!same(e.u, e.v)) 118 { 119 unite(e.u, e.v); 120 res+=e.cost; 121 } 122 } 123 }
Layout(POJ 3169)
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 14477 | Accepted: 6956 |
Description
Input
Output
Sample Input
4 2 1 1 3 10 2 4 20 2 3 3
Sample Output
27
Hint
1 #include <cstdio> 2 #include <queue> 3 #include <cctype> 4 #define num s-‘0‘ 5 using namespace std; 6 7 struct edge 8 { 9 int to; 10 int cost; 11 }; 12 13 const int INF=0x3f3f3f3f; 14 const int MAX_V=1000; 15 vector<edge> G[MAX_V]; 16 int V, ML, MD; 17 int d[MAX_V]; 18 bool inque[MAX_V]; 19 int n[MAX_V]; 20 21 void read(int &x){ 22 char s; 23 x=0; 24 bool flag=0; 25 while(!isdigit(s=getchar())) 26 (s==‘-‘)&&(flag=true); 27 for(x=num;isdigit(s=getchar());x=x*10+num); 28 (flag)&&(x=-x); 29 } 30 31 void write(int x) 32 { 33 if(x<0) 34 { 35 putchar(‘-‘); 36 x=-x; 37 } 38 if(x>9) 39 write(x/10); 40 putchar(x%10+‘0‘); 41 } 42 43 bool spfa(); 44 45 int main() 46 { 47 read(V); read(ML); read(MD); 48 for (int i=0; i<ML; i++) 49 { 50 int A, B, C; 51 read(A); read(B); read(C); 52 edge e; 53 e.to=B-1;e.cost=C; 54 G[A-1].push_back(e); 55 } 56 for (int i=0; i<MD; i++) 57 { 58 int A, B, C; 59 read(A); read(B); read(C); 60 edge e; 61 e.to=A-1;e.cost=-C; 62 G[B-1].push_back(e); 63 } 64 for (int i=0; i<V-1; i++) 65 { 66 edge e; 67 e.to=i;e.cost=0; 68 G[i+1].push_back(e); 69 } 70 if (spfa()) 71 { 72 if (d[V-1]==INF) write(-2); 73 else write(d[V-1]); 74 } 75 else write(-1); 76 } 77 78 bool spfa() 79 { 80 fill(d, d+V, INF); 81 fill(inque, inque+V, false); 82 fill(n, n+V, 0); 83 queue<int> que; 84 d[0]=0; 85 que.push(0); 86 n[0]++; 87 inque[0]=true; 88 while (!que.empty()) 89 { 90 int v=que.front();que.pop(); 91 inque[v]=false; 92 for (int i=0; i<G[v].size(); i++) 93 { 94 if (d[G[v][i].to]>d[v]+G[v][i].cost) 95 { 96 d[G[v][i].to]=d[v]+G[v][i].cost; 97 if (!inque[G[v][i].to]) 98 { 99 que.push(G[v][i].to); 100 inque[G[v][i].to]=true; 101 if (++n[G[v][i].to]>V) return false; 102 } 103 } 104 } 105 } 106 return true; 107 }
原文:https://www.cnblogs.com/Ymir-TaoMee/p/9448406.html