给定有向图,每条边只能用一次,求给定两点间有几条最短路。

来源:互联网 发布:西安交大远程网络教育 编辑:程序博客网 时间:2024/05/29 08:46
  1. 先用flyd求出所有最短路,之后用最短路建图就网络流。
  2. 重点是如何利用最短路建图!!



  3. #include<cstdio>  
  4. #include<cstring>  
  5. #include<queue>  
  6. #define find_min(a,b) a<b?a:b  
  7. using namespace std;  
  8.   
  9. const int N = 210;  
  10. const int MAX = 9999999999;  
  11.   
  12. struct Edge{  
  13.     int s,e,v,next;  
  14. }edge[5*N];  
  15.   
  16. int e_num,head[N],d[N],sp,tp;  
  17. int n,dist[N][N],mat[N][N];  
  18.   
  19. void AddEdge(int a,int b,int c){  
  20.     edge[e_num].s=a; edge[e_num].e=b; edge[e_num].v=c;  
  21.     edge[e_num].next=head[a]; head[a]=e_num++;  
  22.   
  23.     edge[e_num].s=b; edge[e_num].e=a; edge[e_num].v=0;  
  24.     edge[e_num].next=head[b]; head[b]=e_num++;  
  25. }  
  26.   
  27. int bfs(){  
  28.     queue <int> q;  
  29.     memset(d,-1,sizeof(d));  
  30.     d[sp]=0;  
  31.     q.push(sp);  
  32.     while(!q.empty()){  
  33.         int cur=q.front();  
  34.         q.pop();  
  35.         for(int i=head[cur];i!=-1;i=edge[i].next){  
  36.             int u=edge[i].e;  
  37.             if(d[u]==-1 && edge[i].v>0){//没有标记,且可行流大于0  
  38.                 d[u]=d[cur]+1;  
  39.                 q.push(u);  
  40.             }  
  41.         }  
  42.     }  
  43.     return d[tp] != -1;//汇点是否成功标号,也就是说是否找到增广路  
  44. }  
  45.   
  46. int dfs(int a,int b){//a为起点  
  47.     int r=0;  
  48.     if(a==tp)return b;  
  49.     for(int i=head[a];i!=-1 && r<b;i=edge[i].next){  
  50.         int u=edge[i].e;  
  51.         if(edge[i].v>0 && d[u]==d[a]+1){  
  52.             int x=find_min(edge[i].v,b-r);  
  53.             x=dfs(u,x);  
  54.             r+=x;  
  55.             edge[i].v-=x;  
  56.             edge[i^1].v+=x;  
  57.         }  
  58.     }  
  59.     if(!r)d[a]=-2;  
  60.     return r;  
  61. }  
  62.   
  63. void dinic(int sp,int tp){  
  64.     int total=0,t;  
  65.     while(bfs()){  
  66.         while(t=dfs(sp,MAX))  
  67.         total+=t;  
  68.     }  
  69.     printf("%d\n",total);  
  70. }  
  71. int main()  
  72. {  
  73.     int i,j,k;  
  74.     while(~scanf("%d",&n)){      
  75.         for(i=0;i<n;i++){  
  76.             for(j=0;j<n;j++){  
  77.                 scanf("%d",&mat[i][j]);  
  78.                 if(i==j)mat[i][j]=0;  
  79.                 if(mat[i][j]==-1)mat[i][j]=MAX;  
  80.                 dist[i][j]=mat[i][j];  
  81.             }  
  82.         }scanf("%d%d",&sp,&tp);  
  83.           
  84.         if(sp!=tp){  
  85.             for(k=0;k<n;k++){  
  86.                 for(i=0;i<n;i++)  
  87.                     if(dist[i][k]<MAX)for(j=0;j<n;j++)  
  88.                         if(dist[k][j]<MAX)dist[i][j]=find_min(dist[i][j],dist[i][k]+dist[k][j]);  
  89.             }  
  90.               
  91.             e_num=0;  
  92.             memset(head,-1,sizeof(head));  
  93.             for(i=0;i<n;i++){  
  94.                 if(dist[sp][i]<MAX)for(j=0;j<n;j++)  
  95.                     if(dist[j][tp]<MAX && mat[i][j]<MAX && dist[sp][i]+mat[i][j]+dist[j][tp]==dist[sp][tp])AddEdge(i,j,1);  
  96.             }  
  97.   
  98.             dinic(sp,tp);  
  99.         }  
  100.         else puts("inf");  
  101.     }      
  102.     return 0;      
  103. }  

阅读全文
0 0
原创粉丝点击