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 }
View Code

 

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 }
View Code

 

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 }
View Code

 

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 }
View Code

 

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 }
View Code

 

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 }
View Code

 

posted @ 2018-04-25 19:31  LBNOQYX  阅读(196)  评论(0编辑  收藏  举报