hdu3416 Marriage Match IV 最短路+ 最大流

  此题的大意:给定一幅有向图,求起点到终点(都是固定的)的不同的最短路有多少条。不同的最短路是说不能有相同的边,顶点可以重复。并且图含有平行边。

  看了题以后,就想到暴力,但是暴力往往是不可取的。(暴力的最坏情况下的时间复杂度是O(n^3))。我说的暴力是求一次最短路以后,把最短路上的边全部去掉(权值设为INF)。

  最短路可以有很多条,但是最短路的值只有一个。根据这个,我们可以判断某条边是否在最短路上。

  建图(单向边),求最短路,起点就是输入的起点。枚举每一条边,如果满足dist[i]+Map[i][j]==dist[j],就建立一条权值为i,j之间长度等于最短边的边数。

  我的做法是在建正向图的时候,用数组en[][]记录两点之间的长度等于最短边的边数。

  看上去代码蛮长的,其实就2个模版,main()才是需要自己去写的。

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 using namespace std;
  6 const int N = 1010, M=2000010, INF=100001000;
  7 int dist[N], Map[N][N], pre[N],en[N][N];
  8 bool p[N];
  9 void Dijkstra(int s,int n)
 10 {
 11     int i,j,k, MIN;
 12     for(i=1; i<=n; i++) //初始化
 13     {
 14         p[i]=0;
 15         if(i!=s)
 16         {
 17             dist[i]= Map[s][i];
 18             pre[i]=s;
 19         }
 20     }
 21     dist[s]=0;
 22     p[s]=1;
 23     for(i=1; i<n; i++) //循环n-1次
 24     {
 25         MIN=INF;
 26         k=0;
 27         for(j=1; j<=n; j++)
 28         {
 29             if(!p[j]&&dist[j]<MIN)
 30             {
 31                 MIN= dist[j];
 32                 k=j;
 33             }
 34         }
 35         if(!k) return ;//没有点可以扩展
 36         p[k]=1; //将k从Vb中除去,加入Va
 37         for(j=1; j<=n; j++)
 38         {
 39             if(!p[j]&&Map[k][j]!=INF&&dist[j]>dist[k]+Map[k][j])
 40             {
 41                 dist[j]= dist[k] + Map[k][j];
 42                 pre[j]=k;
 43             }
 44         }
 45     }
 46 }
 47 struct node
 48 {
 49     int to,next,w;
 50 }edge[M];
 51 int head[N],numh[N],h[N],cure[N];
 52 int ans,tot;
 53 void SAP(int s, int e,int n)
 54 {
 55     int flow,u,tmp,neck,i;
 56     ans=0;
 57     for(i=1;i<=n;i++)
 58         cure[i]=head[i];
 59     numh[0]=n;
 60     u=s;
 61     while(h[s]<n)
 62     {
 63         if(u==e)
 64         {
 65             flow =INF;
 66             for(i=s;i!=e;i=edge[cure[i]].to)
 67             {
 68                 if(flow>edge[cure[i]].w)
 69                 {
 70                     neck=i;
 71                     flow =edge[cure[i]].w;
 72                 }
 73             }
 74             for(i=s;i!=e;i=edge[cure[i]].to)
 75             {
 76                 tmp=cure[i];
 77                 edge[tmp].w-=flow;
 78                 edge[tmp^1].w+=flow;
 79             }
 80             ans+=flow;
 81             u=neck;
 82         }
 83         for(i=cure[u];i!=-1;i=edge[i].next)
 84             if(edge[i].w && h[u]==h[edge[i].to]+1) break;
 85         if(i!=-1) {cure[u]=i;pre[edge[i].to]=u;u=edge[i].to;}
 86         else
 87         {
 88             if(0==--numh[h[u]]) break; //GAP优化
 89             cure[u]=head[u];
 90             for(tmp=n,i=head[u];i!=-1;i=edge[i].next)
 91                 if(edge[i].w) tmp=min(tmp, h[edge[i].to]);
 92             h[u]=tmp+1;
 93             ++numh[h[u]];
 94             if(u!=s) u=pre[u];
 95         }
 96     }
 97 }
 98 void init()
 99 {
100     tot=0;
101     memset(head,-1,sizeof(head));
102     memset(pre,-1,sizeof(pre));
103     memset(h,0,sizeof(h));
104     memset(numh,0,sizeof(numh));
105 
106 }
107 void addedge(int i,int j,int w)
108 {
109     edge[tot].to=j;edge[tot].w=w;edge[tot].next=head[i];head[i]=tot++;
110     edge[tot].to=i;edge[tot].w=0;edge[tot].next=head[j];head[j]=tot++;
111 }
112 int main()
113 {
114     //freopen("test.txt","r",stdin);
115     int n,m,i,j,k,s,e,cas;
116     scanf("%d",&cas);
117     while(cas--)
118     {
119         scanf("%d%d",&n,&m);
120         for(i=1;i<=n;i++)
121             for(j=1;j<=n;j++)
122         {
123             Map[i][j]=INF;
124             en[i][j]=0;
125         }
126         while(m--)
127         {
128             scanf("%d%d%d",&i,&j,&k);
129             if(i==j) continue;
130             if(Map[i][j]>k) {Map[i][j]=k, en[i][j]=1;}
131             else if (Map[i][j]==k) {en[i][j]++;}
132         }
133         scanf("%d%d",&s,&e);
134         Dijkstra(s,n);
135         init();
136         for(i=1;i<=n;i++)
137         {
138             for(j=1;j<=n;j++)
139             {
140                 if(Map[i][j]!=INF)
141                 {
142                     if(dist[i]+Map[i][j]==dist[j])
143                         addedge(i,j,en[i][j]);
144                 }
145             }
146         }
147         SAP(s,e,n);
148         printf("%d\n",ans);
149     }
150     return 0;
151 }
View Code

 

posted @ 2014-09-15 22:48  pengmq  阅读(242)  评论(0编辑  收藏  举报