2010年02月10日星期三.sgu185 dijkstra + 流

2010年02月10日星期三.sgu185 dijkstra + 流

2010年02月10日星期三.sgu185
ALGO:dijkstra + 流
求两条没有相同边的最短路。
直觉的想法是求一条,然后把这条相关的删掉,再求另外一条
但是这种想法是不正确的。

引用
http://www.answeror.com/archives/28474 的一组数据来说明这个问题
6 7
1 2 1
1 3 1
2 4 1
3 4 1
3 5 1
4 6 1
5 6 1

如果第一次求出的最短路是1-3-4-6, 那么第二条最短路就不存在了, 但是实际上有两条最短路,
即1-3-5-6和1-2-4-6.
所以需要调整,调整的思想让我们想到了流。

保留图中所有能构成任何一条最短路的边,将所有边的容量设为1.  然后对这个图求两次增广路。
由于容量的限制,所以求得的两条最短路一定是没有公共边的,这时按照流的方向,输出这两条
路径即可。

注意:不要按照增广时的顶点顺序输出最短路,这样是不对的,同样可以使用上面的那组数据,
如果先增广的是 1-3-4-6这条路径的话,那么输出的结果就会不正确了。 我就是这么wa@test 20 好久的。

  1 
  2  const   int  N  =   401 ;
  3  const   int  inf  =   1   <<   20 ;
  4  int  dis[N],vis[N],n,m;
  5  int  g1[N][N],g2[N][N],p[N],f[N][N];
  6 
  7  bool  dijkstra()
  8  {
  9     int  i,j,k;
 10    memset(vis, 0 , sizeof (vis));
 11    dis[ 1 =   0 ,vis[ 1 =   true ;
 12     for  (i  =   2 ;i  <=  n;i ++ ) {
 13        dis[i]  =  g1[ 1 ][i];
 14    }
 15     for  (k  =   2 ;k  <=  n;k ++ ) {
 16         int  min  =  inf,idx  =   1 ;
 17         for  (i  =   2 ;i  <=  n;i ++ ) {
 18             if  (dis[i]  <  min  &&   ! vis[i]) {
 19                min  =  dis[i],idx  =  i;
 20            }
 21        }
 22         if  (idx  ==   1 ) {  break ; }
 23        vis[idx]  =   true ;
 24         for  (i  =   1 ;i  <=  n;i ++ ) {
 25             if  (dis[i]  >  min  +  g1[idx][i]) {
 26                dis[i]  =  min  +  g1[idx][i];
 27            }
 28        }
 29    }
 30     for  (i  =   1 ;i  <=  n;i ++ ) {
 31         for  (j  =   1 ;j  <=  n;j ++ ) {
 32             if  (dis[i]  +  g1[i][j]  ==  dis[j]) {
 33                g2[i][j]  =   1 ;
 34            }
 35        }
 36    }
 37     return  dis[n]  !=  inf;
 38  }
 39 
 40  bool  bfs()
 41  {
 42    memset(vis, 0 , sizeof (vis));
 43    memset(p, 0 , sizeof (p));
 44    queue < int >  que;
 45    que.push( 1 ),vis[ 1 =   true ;
 46     while  ( ! que.empty()) {
 47         int  u  =  que.front(); que.pop();
 48         for  ( int  v  =   2 ;v  <=  n;v ++ ) {
 49             if  ( ! vis[v]  &&  g2[u][v]) {
 50                p[v]  =  u,vis[v]  =   true ;
 51                 if  (v  ==  n) {
 52                     for  (v  =  n;v  !=   1 ;v  =  p[v]) {
 53                        u  =  p[v];
 54                        g2[u][v]  -- ;
 55                        g2[v][u]  ++ ;
 56                         if  (f[v][u]  >   0 ) {
 57                            f[v][u] -- ;
 58                        } else  {
 59                            f[u][v]  ++ ;
 60                        }
 61                    }
 62                     return   true ;
 63                }
 64                que.push(v);
 65            }
 66        }
 67    }
 68     return   false ;
 69  }
 70 
 71  void  pr( int  u)
 72  {
 73     if  (u  ==  n) {
 74        printf( " %d\n " ,u);
 75         return ;
 76    }
 77     for  ( int  i  =   1 ;i  <=  n;i ++ ) {
 78         if  (f[u][i]  >   0 ) {
 79            f[u][i]  -- ;
 80            printf( " %d  " ,u);
 81            pr(i);
 82             return  ;
 83        }
 84    }
 85  }
 86 
 87  bool  EK()
 88  {
 89     if  (bfs()  &&  bfs()) {
 90        pr( 1 ), pr( 1 );
 91         return   true ;
 92    }
 93     return   false ;
 94  }
 95 
 96 
 97  int  main()
 98  {
 99     int  i,j,a,b,c;
100    scanf( " %d%d " , & n, & m);
101     for  (i  =   1 ;i  <=  n;i ++ ) {
102         for  (j  =   1 ;j  <=  n;j ++ ) {
103            g1[i][j]  =  inf;
104        }
105    }
106     for  (i  =   0 ;i  <  m;i ++ ) {
107        scanf( " %d%d%d " , & a, & b, & c);
108         if  (g1[a][b]  >  c) {
109            g1[a][b]  =  g1[b][a]  =  c;
110        }
111    }
112     if  ( ! dijkstra()  ||   ! EK()){
113        printf( " No solution\n " );
114    }
115     return   0 ;
116  }
117 


你可能感兴趣的:(2010年02月10日星期三.sgu185 dijkstra + 流)