zoukankan      html  css  js  c++  java
  • 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
    ", 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
    ", 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
    ", 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
    ", dinic() );
    187     }
    188     return 0;
    189 }
    View Code
  • 相关阅读:
    数据库基础知识复习-2013.09.24
    2013.9.24 答题
    使用单向循环链表实现约瑟夫问题
    C++关于数字逆序输出的两种思路,及字符串逆序输出
    题目要求:建立一个类Str,将一个正整数转换成相应的字符串,例如整数3456转换为字符串"3456".
    将博客搬至CSDN
    Android 下载模块分析(DownloadManager和DownloadProvider)
    linux shell基础语法
    Android过滤Logcat输出
    (Java 多线程系列)Java 线程池(Executor)
  • 原文地址:https://www.cnblogs.com/chaoswr/p/8946732.html
Copyright © 2011-2022 走看看