kuangbin带我飞QAQ 最短路
1. poj 1502 Mathches Game
裸最短路
1 #include <iostream> 2 #include <string.h> 3 #include <cstdio> 4 #include <queue> 5 #include <vector> 6 #include <string> 7 #include <cstring> 8 #include <algorithm> 9 #include <math.h> 10 11 #define SIGMA_SIZE 26 12 #pragma warning ( disable : 4996 ) 13 14 using namespace std; 15 typedef long long LL; 16 17 inline LL LMax(LL a,LL b) { return a>b?a:b; } 18 inline LL LMin(LL a,LL b) { return a>b?b:a; } 19 inline int Max(int a,int b) { return a>b?a:b; } 20 inline int Min(int a,int b) { return a>b?b:a; } 21 inline int gcd( int a, int b ) { return b==0?a:gcd(b,a%b); } 22 inline int lcm( int a, int b ) { return a/gcd(a,b)*b; } //a*b = gcd*lcm 23 const long long INF = 0x3f3f3f3f3f3f3f3f; 24 const int inf = 0x3f3f3f3f; 25 const int mod = 7; 26 const int maxk = 110; 27 const int maxn = 110; 28 29 struct edge { 30 int to, next, val; 31 }e[maxn*maxn]; 32 33 34 int dis[maxn], linjie[maxn]; 35 bool vis[maxn]; 36 int N, cnt, ans; 37 38 void addedge( int x, int y, int val ) 39 { 40 e[cnt].to = y; e[cnt].next = linjie[x]; e[cnt].val = val; linjie[x] = cnt++; } 41 42 void init() 43 { 44 cnt = ans = 0; 45 memset( linjie, -1, sizeof(linjie) ); 46 memset( dis, 0x3f, sizeof(dis) ); 47 memset( vis, 0, sizeof(vis) ); 48 } 49 50 void read() 51 { 52 init(); 53 string str; 54 int tmp = 1; 55 56 for ( int i = 1; i < N; i++ ) 57 { 58 for ( int j = 0; j < tmp; j++ ) 59 { 60 int val = 0; 61 cin >> str; 62 63 if ( str == "x" ) 64 continue; 65 int len = str.length(); 66 67 int x = 1; 68 for ( int k = len - 1; k >= 0; k-- ) 69 { 70 val += (str[k]-'0')*x; 71 x *= 10; 72 } 73 addedge( i, j, val ); 74 addedge( j, i, val ); 75 } 76 tmp++; 77 } 78 } 79 80 void dijkstra() 81 { 82 dis[0] = 0; 83 84 for ( int i = 0; i < N; i++ ) 85 { 86 int mindis = inf, mark = -1; 87 for ( int j = 0; j < N; j++ ) 88 if ( !vis[j] && dis[j] < mindis ) 89 { 90 mark = j; 91 mindis = dis[j]; 92 } 93 94 vis[mark] = true; 95 96 for ( int j = linjie[mark]; j+1; j = e[j].next ) 97 if (!vis[e[j].to]) 98 { 99 int v = e[j].to, val = e[j].val; 100 dis[v] = Min(dis[v], dis[mark]+val); 101 } 102 } 103 } 104 105 int main() 106 { 107 cin >> N; 108 109 read(); 110 dijkstra(); 111 112 for ( int i = 0; i < N; i++ ) 113 ans = Max( ans, dis[i] ); 114 115 cout << ans << endl; 116 return 0; 117 }
2. poj 3660 cow contest
floyd 求传递闭包
1 #include <iostream> 2 #include <string.h> 3 #include <cstdio> 4 #include <queue> 5 #include <vector> 6 #include <string> 7 #include <cstring> 8 #include <algorithm> 9 #include <math.h> 10 11 #define SIGMA_SIZE 26 12 #pragma warning ( disable : 4996 ) 13 14 using namespace std; 15 typedef long long LL; 16 17 inline LL LMax(LL a,LL b) { return a>b?a:b; } 18 inline LL LMin(LL a,LL b) { return a>b?b:a; } 19 inline int Max(int a,int b) { return a>b?a:b; } 20 inline int Min(int a,int b) { return a>b?b:a; } 21 inline int gcd( int a, int b ) { return b==0?a:gcd(b,a%b); } 22 inline int lcm( int a, int b ) { return a/gcd(a,b)*b; } //a*b = gcd*lcm 23 const long long INF = 0x3f3f3f3f3f3f3f3f; 24 const int inf = 0x3f3f3f3f; 25 const int mod = 7; 26 const int maxk = 110; 27 const int maxn = 110; 28 29 bool mmap[maxn][maxn]; 30 int ojbk[maxn]; 31 int N, M; 32 33 void floyd() 34 { 35 for ( int k = 1; k <= N; k++ ) 36 for ( int i = 1; i <= N; i++ ) 37 for ( int j = 1; j <= N; j++ ) 38 { 39 mmap[i][j] = (mmap[i][j] || (mmap[i][k] && mmap[k][j])); 40 } 41 } 42 43 int main() 44 { 45 cin >> N >> M; 46 47 int x, y; 48 for ( int i = 1; i <= M; i++ ) 49 { 50 scanf("%d %d", &x, &y); 51 mmap[x][y] = 1; 52 } 53 54 floyd(); 55 56 int ans = 0; 57 for ( int i = 1; i <= N; i++ ) 58 for ( int j = 1; j <= N; j++ ) 59 if ( mmap[i][j] ) 60 { 61 ojbk[i]++; 62 ojbk[j]++; 63 } 64 65 for ( int i = 1; i <= N; i++ ) 66 if ( ojbk[i] == N-1 ) 67 ans++; 68 cout << ans << endl; 69 70 return 0; 71 }
3. poj 1511 Invitation Cards
双向最短路,正着求一次,边取反再求一次
1 #include <iostream> 2 #include <string.h> 3 #include <cstdio> 4 #include <queue> 5 #include <map> 6 #include <vector> 7 #include <string> 8 #include <cstring> 9 #include <algorithm> 10 #include <math.h> 11 12 #define SIGMA_SIZE 26 13 #pragma warning ( disable : 4996 ) 14 15 using namespace std; 16 typedef long long LL; 17 18 inline LL LMax(LL a,LL b) { return a>b?a:b; } 19 inline LL LMin(LL a,LL b) { return a>b?b:a; } 20 inline int Max(int a,int b) { return a>b?a:b; } 21 inline int Min(int a,int b) { return a>b?b:a; } 22 inline int gcd( int a, int b ) { return b==0?a:gcd(b,a%b); } 23 inline int lcm( int a, int b ) { return a/gcd(a,b)*b; } //a*b = gcd*lcm 24 const long long INF = 0x3f3f3f3f3f3f3f3f; 25 const int inf = 0x3f3f3f3f; 26 const int mod = 7; 27 const int maxk = 110; 28 const int maxn = 1e6+5; 29 30 int num[3*maxn]; 31 int linjie[maxn]; 32 int dis[maxn]; 33 bool vis[maxn]; 34 int P, Q, cnt; 35 long long ans; 36 37 struct edge { 38 int to, next, val ; 39 }e[maxn]; 40 41 struct cmp { 42 bool operator() ( const int a, const int b ) 43 { return dis[a]>dis[b]; } 44 }; 45 46 void addedge( int u, int v, int val ) 47 { e[cnt].to = v; e[cnt].next = linjie[u]; e[cnt].val = val; linjie[u] = cnt++; } 48 49 void init() 50 { 51 cnt = 0; ans = 0; 52 memset( linjie, -1, sizeof(linjie) ); 53 } 54 55 void dijkstra() 56 { 57 memset( dis, 0x3f, sizeof(dis) ); 58 memset( vis, 0, sizeof(vis) ); 59 60 priority_queue<int, vector<int>, cmp> q; 61 dis[1] = 0; 62 q.push(1); 63 64 while (!q.empty()) 65 { 66 int run = q.top(); q.pop(); 67 int mindis = dis[run]; 68 69 vis[run] = true; 70 71 for ( int i = linjie[run]; i+1; i = e[i].next ) 72 if ( !vis[e[i].to] && dis[e[i].to] > mindis + e[i].val ) 73 { 74 dis[e[i].to] = mindis + e[i].val; 75 q.push(e[i].to); 76 } 77 } 78 for ( int i = 2; i <= P; i++ ) 79 ans += (long long)dis[i]; 80 } 81 82 int main() 83 { 84 int n; 85 cin >> n; 86 87 while (n--) 88 { 89 init(); 90 scanf( "%d %d", &P, &Q ); 91 92 int j = 1; 93 for ( int i = 1; i <= Q; i++ ) 94 { 95 scanf( "%d %d %d", &num[j], &num[j+1], &num[j+2] ); 96 addedge( num[j], num[j+1], num[j+2] ); 97 j += 3; 98 } 99 dijkstra(); 100 101 //重新建边/// 102 memset( linjie, -1, sizeof(linjie) ); 103 cnt = 0; j = 1; 104 for ( int i = 1; i <= Q; i++ ) 105 { 106 addedge( num[j+1], num[j], num[j+2] ); 107 j += 3; 108 } 109 110 dijkstra(); 111 112 printf( "%lld\n", ans ); 113 } 114 115 return 0; 116 }
4.poj 3159 Candies
dijsktra+优先队列优化+差分约束
1 #include <iostream> 2 #include <string.h> 3 #include <stdio.h> 4 #include <algorithm> 5 #include <queue> 6 #include <vector> 7 #define SIGMA_SIZE 26 8 #pragma warning ( disable : 4996 ) 9 10 using namespace std; 11 typedef long long LL; 12 13 inline LL LMax(LL a,LL b) { return a>b?a:b; } 14 inline LL LMin(LL a,LL b) { return a>b?b:a; } 15 inline int Max(int a,int b) { return a>b?a:b; } 16 inline int Min(int a,int b) { return a>b?b:a; } 17 inline int gcd( int a, int b ) { return b==0?a:gcd(b,a%b); } 18 inline int lcm( int a, int b ) { return a/gcd(a,b)*b; } //a*b = gcd*lcm 19 const long long INF = 0x3f3f3f3f3f3f3f3f; 20 const int inf = 0x3f3f3f3f; 21 const int mod = 7; 22 const int maxk = 200000 + 5; 23 const int maxn = 50000 + 5; 24 25 int linjie[maxn]; 26 int dis[maxn]; 27 bool vis[maxn]; 28 int P, Q, cnt; 29 30 struct qnode 31 { 32 int v; 33 int c; 34 qnode(int _v=0,int _c=0):v(_v),c(_c){} 35 bool operator <(const qnode &r)const 36 { 37 return c>r.c; 38 } 39 }; 40 41 struct edge { 42 int to, next, val ; 43 }e[maxk]; 44 45 void addedge( int u, int v, int val ) 46 { e[cnt].to = v; e[cnt].next = linjie[u]; e[cnt].val = val; linjie[u] = cnt++; } 47 48 void init() 49 { 50 cnt = 0; 51 memset( linjie, -1, sizeof(linjie) ); 52 } 53 54 void dijkstra() 55 { 56 memset( dis, 0x3f, sizeof(dis) ); 57 memset( vis, 0, sizeof(vis) ); 58 59 priority_queue<qnode> q; 60 while(!q.empty()) q.pop(); 61 dis[1] = 0; 62 q.push(qnode(1,0)); 63 64 qnode tmp; 65 66 while (!q.empty()) 67 { 68 tmp = q.top(); q.pop(); 69 int run = tmp.v; 70 int mindis = dis[run]; 71 72 vis[run] = true; 73 74 for ( int i = linjie[run]; i+1; i = e[i].next ) 75 if ( !vis[e[i].to] && dis[e[i].to] > mindis + e[i].val ) 76 { 77 int v = e[i].to; 78 dis[v] = mindis + e[i].val; 79 q.push(qnode(v, dis[v])); 80 } 81 } 82 } 83 84 int main() 85 { 86 init(); 87 scanf( "%d%d", &P, &Q ); 88 89 90 int x, y, z; 91 for ( int i = 1; i <= Q; i++ ) 92 { 93 scanf( "%d%d%d", &x, &y, &z ); 94 addedge(x,y,z); 95 } 96 97 dijkstra(); 98 99 printf( "%d\n", dis[P] ); 100 101 return 0; 102 }
5. poj 3169 Layout
spfa+负环+差分约束
最经典的差分约束,因为求的是dis[N]-dis[1]的最大值 ,即dis[N]-dis[1] <= x,所以用最短路。用spfa判断若有负环,说明最短路无限小,所以无解;若dis[N] = inf,说明最短路可以无限大,
1 #include <iostream> 2 #include <string.h> 3 #include <cstdio> 4 #include <queue> 5 #include <map> 6 #include <vector> 7 #include <string> 8 #include <cstring> 9 #include <algorithm> 10 #include <math.h> 11 12 #define SIGMA_SIZE 26 13 #pragma warning ( disable : 4996 ) 14 15 using namespace std; 16 typedef long long LL; 17 18 inline LL LMax(LL a,LL b) { return a>b?a:b; } 19 inline LL LMin(LL a,LL b) { return a>b?b:a; } 20 inline int Max(int a,int b) { return a>b?a:b; } 21 inline int Min(int a,int b) { return a>b?b:a; } 22 inline int gcd( int a, int b ) { return b==0?a:gcd(b,a%b); } 23 inline int lcm( int a, int b ) { return a/gcd(a,b)*b; } //a*b = gcd*lcm 24 const long long INF = 0x3f3f3f3f3f3f3f3f; 25 const int inf = 0x3f3f3f3f; 26 const int mod = 7; 27 const int maxk = 2e4+5; 28 const int maxn = 1010; 29 30 int N, Ml, Md, cnt; 31 int linjie[maxn], in[maxn]; 32 bool vis[maxn]; 33 long long dis[maxn]; 34 35 struct edge { 36 int to, next, val; 37 }e[maxk]; 38 39 void addedge( int u, int v, int val ) 40 { 41 e[cnt].to = v; 42 e[cnt].next = linjie[u]; 43 e[cnt].val = val; 44 linjie[u] = cnt++; 45 } 46 47 void init() 48 { 49 cnt = 0; 50 memset( linjie, -1, sizeof(linjie) ); 51 } 52 53 long long spfa() 54 { 55 memset( dis, 0x3f, sizeof(dis) ); 56 57 queue<int> q; 58 q.push(1); dis[1] = 0; 59 60 while ( !q.empty() ) 61 { 62 int run = q.front(); q.pop(); 63 vis[run] = false; 64 65 for ( int i = linjie[run]; i+1; i = e[i].next ) 66 { 67 int v = e[i].to, cost = e[i].val; 68 if ( dis[v] > dis[run] + cost ) 69 { 70 dis[v] = dis[run] + cost; 71 if (!vis[v]) 72 { 73 in[v]++; 74 if ( in[v] > N ) return -1; 75 76 vis[v] = true; 77 q.push(v); 78 } 79 } 80 } 81 } 82 83 if ( dis[N] == INF ) return -2; 84 else 85 return dis[N]; 86 } 87 88 int main() 89 { 90 init(); 91 cin >> N >> Ml >> Md; 92 93 //差分约束条件建边 94 int a, b, z; 95 for ( int i = 1; i <= Ml; i++ ) 96 { scanf("%d%d%d", &a, &b, &z); addedge(a,b,z); } 97 for ( int i = 1; i <= Md; i++ ) 98 { scanf("%d%d%d", &a, &b, &z); addedge(b,a,-z); } 99 100 printf( "%lld\n", spfa() ); 101 return 0; 102 }
6. hdu3416 Marriage Match IV
dijkstra+最大流dinic当前弧优化
hdu的题好难...这题最不一样的是求一共有多少条最短路(路径不可以重复),一个暴力的想法就是求一条最短路再删去该路的所有边,再求最短路,再删边,直到求得最短路长度大于第一次求得的长度为止,不过用脚趾头想都知道数据肯定会卡你的。
其实会发现如果抛弃最短路来看,这道题很像最大流,就是所有边权为1求最大流的题目,不过现在加了约束条件必须在最短路上取最大流。所以我们可以求出所有的最短路径的边并重新建一个边权为1的图,在其上做最大流就可以了,那么怎么求所有最短路径呢?
有个方法是从终点dijkstra一下再从起点dijkstra下(注意要建立反向边图),假设dis1[u]表示start-u之间最短距离,dis2[v]表示v-end之间最短距离,那么只要dis1[u]+dis2[v]+dis[u][v] == 最短路长度,就代表这条边是可以要的
1 #include <iostream> 2 #include <string.h> 3 #include <cstdio> 4 #include <queue> 5 #include <map> 6 #include <vector> 7 #include <string> 8 #include <cstring> 9 #include <algorithm> 10 #include <math.h> 11 12 #define SIGMA_SIZE 26 13 #pragma warning ( disable : 4996 ) 14 15 using namespace std; 16 typedef long long LL; 17 18 inline LL LMax(LL a,LL b) { return a>b?a:b; } 19 inline LL LMin(LL a,LL b) { return a>b?b:a; } 20 inline int Max(int a,int b) { return a>b?a:b; } 21 inline int Min(int a,int b) { return a>b?b:a; } 22 inline int gcd( int a, int b ) { return b==0?a:gcd(b,a%b); } 23 inline int lcm( int a, int b ) { return a/gcd(a,b)*b; } //a*b = gcd*lcm 24 const long long INF = 0x3f3f3f3f3f3f3f3f; 25 const int inf = 0x3f3f3f3f; 26 const int mod = 7; 27 const int maxk = 1e5+5; 28 const int maxn = 1010; 29 30 int N, M, cnt; 31 int st, ed; 32 int num[maxk*3]; 33 int disst[maxn], dised[maxn], cur[maxn]; 34 int linjie1[maxn], linjie2[maxn]; 35 bool vis[maxn]; 36 37 struct node { 38 int to, next, val; 39 }e1[maxk], e2[maxk]; 40 41 void addedge1( int u, int v, int val ) 42 { e1[cnt].to = v; e1[cnt].val = val; e1[cnt].next = linjie1[u]; linjie1[u] = cnt++; } 43 void addedge2( int u, int v, int val ) 44 { e2[cnt].to = v; e2[cnt].val = val; e2[cnt].next = linjie2[u]; linjie2[u] = cnt++; } 45 46 void init() 47 { 48 cnt = 0; 49 memset( linjie1, -1, sizeof(linjie1) ); 50 memset( linjie2, -1, sizeof(linjie2) ); 51 } 52 53 void dijkstra( int x ) 54 { 55 memset( vis, 0, sizeof(vis) ); 56 memset( disst, 0x3f, sizeof(disst) ); 57 disst[x] = 0; 58 59 for ( int k = 1; k <= N; k++ ) 60 { 61 int mark = -1, mindis = inf; 62 for ( int i = 1; i <= N; i++ ) 63 if ( !vis[i] && disst[i] < mindis ) 64 { 65 mark = i; 66 mindis = disst[i]; 67 } 68 vis[mark] = true; 69 70 for ( int i = linjie1[mark]; i+1; i = e1[i].next ) 71 { 72 int v = e1[i].to, cost = e1[i].val; 73 if ( !vis[v] && disst[v] > disst[mark] + cost ) 74 disst[v] = disst[mark] + cost; 75 } 76 } 77 } 78 79 void make_map() 80 { 81 cnt = 0; 82 int mindist = disst[ed]; 83 84 for ( int i = 1; i <= N; i++ ) 85 for ( int j = linjie1[i]; j + 1; j = e1[j].next ) 86 { 87 int v = e1[j].to, cost = e1[j].val; 88 if ( disst[i] + cost + dised[v] == mindist ) 89 addedge2( i, v, 1 ); 90 } 91 } 92 93 int bfs() 94 { 95 memset( disst, -1, sizeof(disst) ); 96 queue<int> q; 97 98 q.push(st); 99 disst[st] = 0; 100 101 while( !q.empty() ) 102 { 103 int run = q.front(); q.pop(); 104 for( int i = linjie2[run]; i+1; i = e2[i].next ) 105 { 106 int v = e2[i].to, flow = e2[i].val; 107 if( disst[v] < 0 && flow > 0 ) 108 { 109 disst[v] = disst[run] + 1; 110 q.push(v); 111 } 112 } 113 } 114 115 if( disst[ed] > 0 ) 116 return 1; 117 else 118 return 0; 119 } 120 121 int find( int s, int low ) 122 { 123 int ff = 0; 124 if( s == ed ) 125 return low; 126 for( int& i = cur[s]; i+1; i = e2[i].next ) //注意int& i = cur[s] 当前弧优化 127 { 128 int v = e2[i].to, cap = e2[i].val; 129 if( cap > 0 130 && disst[v] == disst[s] + 1 131 && (ff = find(v,Min(cap,low))) ) 132 { 133 e2[i].val -= ff; 134 //e2[i^1].val += ff; 135 return ff; 136 } 137 } 138 return 0; 139 } 140 141 int dinic() 142 { 143 int ans = 0; 144 int tans; 145 while( bfs() ) 146 { 147 for( int i = 1; i <= N; i++ ) //当前弧优化 148 cur[i] = linjie2[i]; 149 while( tans = find( st, inf ) ) 150 ans += tans; 151 } 152 return ans; 153 } 154 155 156 int main() 157 { 158 int T; cin >> T; 159 while (T--) 160 { 161 scanf("%d%d", &N, &M); 162 163 init(); 164 for (int i = 1, j = 1; i <= M; i++) 165 { 166 scanf( "%d%d%d", &num[j], &num[j+1], &num[j+2] ); 167 addedge1(num[j+1],num[j],num[j+2]); 168 j += 3; 169 } 170 171 scanf("%d%d", &st, &ed); 172 173 dijkstra(ed); 174 for ( int i = 1; i <= N; i++ ) 175 dised[i] = disst[i]; 176 cnt = 0; 177 memset( linjie1, -1, sizeof(linjie1) ); 178 for ( int i = 1, j = 1; i <= M; i++ ) 179 { 180 addedge1( num[j], num[j+1], num[j+2] ); 181 j += 3; 182 } 183 dijkstra(st); 184 make_map(); 185 186 printf( "%d\n", dinic() ); 187 } 188 return 0; 189 }
什么时候能够不再这么懒惰