hdu3416 Marriage Match IV(最短路+网络流)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3416

题意:

给出含n个点、m条有向边的图,每条边只能走一次,给出起点和终点,求起点到终点的最短路径有多少条。

思路:

题目要求是最短路径,当然需要求出最短路,用Dijkstra就可以了,然后我们需要构造网络流的图。将能组成最短路的边加入图中,容量设为1,注意能组成最短路的边是满足dis[u] + edge[i].dist == dis[v] 的边,其中u是边的起点,v是边的终点,dis[]保存的是最短路。最后跑最大流即可。

代码如下:

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cmath>
  4 #include<cstring>
  5 #include<queue>
  6 
  7 using namespace std;
  8 const int INF=0x3f3f3f3f;
  9 const int maxn=1100;
 10 const int maxm=110000;
 11 struct node
 12 {
 13     int d,u;
 14     friend bool operator<(node a,node b)
 15     {
 16         return a.d>b.d;
 17     }
 18     node(int dist,int point):d(dist),u(point){}
 19 };
 20 
 21 struct Edge1
 22 {
 23     int to,next;
 24     int dist;
 25 }edge1[maxm];
 26 int head1[maxn],tot;
 27 int pre[maxn],dis[maxn];
 28 bool vis[maxm];
 29 
 30 void init1()
 31 {
 32     memset(head1,-1,sizeof(head1));
 33     tot=0;
 34 }
 35 
 36 void addedge1(int u,int v,int d)
 37 {
 38     edge1[tot].to=v;
 39     edge1[tot].dist=d;
 40     edge1[tot].next=head1[u];
 41     head1[u]=tot++;
 42 }
 43 
 44 void Dijkstra(int s)
 45 {
 46     priority_queue<node> q;
 47     memset(dis,0x3f,sizeof(dis));
 48     memset(pre,-1,sizeof(pre));
 49     dis[s]=0;
 50     while(!q.empty())
 51         q.pop();
 52     node a(0,s);
 53     q.push(a);       
 54     while(!q.empty())
 55     {
 56         node x=q.top();
 57         q.pop();
 58         if(dis[x.u]<x.d)   
 59             continue;
 60         for(int i=head1[x.u];i!=-1;i=edge1[i].next)
 61         {
 62             int v=edge1[i].to;
 63             if(dis[v]>dis[x.u]+edge1[i].dist)
 64             {
 65                 dis[v]=dis[x.u]+edge1[i].dist;
 66                 pre[v]=x.u;
 67                 q.push(node(dis[v],v));
 68             }
 69         }
 70     }
 71 }
 72 const int MAXN = 2010;
 73 const int MAXM = 1200012;
 74 struct Temp
 75 {
 76     int u,v;
 77 }temp[MAXM];
 78 int cnt;
 79 void dfs(int u)
 80 {
 81     for(int i=head1[u];i!=-1;i=edge1[i].next)
 82     {
 83         int v=edge1[i].to;
 84         if(dis[u]+edge1[i].dist==dis[v]&&(!vis[i]))
 85         {
 86             temp[cnt].u=u;
 87             temp[cnt++].v=v;
 88             vis[i]=true;
 89             dfs(v);
 90         }
 91     }
 92 }
 93 
 94 struct Edge2 
 95 {
 96     int to, next, cap, flow;
 97 }edge[MAXM];
 98 int tol;
 99 int head[MAXN];
100 void init() 
101 {
102     tol = 2;
103     memset(head, -1, sizeof(head));
104 }
105 void addedge(int u, int v, int w, int rw=0) 
106 {
107     edge[tol].to = v; edge[tol].cap = w; edge[tol].flow = 0;
108     edge[tol].next = head[u]; head[u] = tol++;
109     edge[tol].to = u; edge[tol].cap = rw; edge[tol].flow = 0;
110     edge[tol].next = head[v]; head[v] = tol++;
111 }
112 int Q[MAXN];
113 int dep[MAXN], cur[MAXN], sta[MAXN];
114 bool bfs(int s, int t, int n) 
115 {
116     int front = 0, tail = 0;
117     memset(dep, -1, sizeof(dep[0])*(n+1));
118     dep[s] = 0;
119     Q[tail++] = s;
120     while(front < tail)
121     {
122         int u = Q[front++];
123         for(int i = head[u]; i != -1; i = edge[i].next) 
124         {
125             int v = edge[i].to;
126             if(edge[i].cap > edge[i].flow && dep[v] == -1)                         {
127                 dep[v] = dep[u] + 1;
128                 if(v == t) return true;
129                 Q[tail++] = v;
130             }
131         }
132     }
133     return false;
134 }
135 int dinic(int s, int t, int n) {
136     int maxflow = 0;
137     while(bfs(s, t, n)) {
138         for(int i = 0; i < n; i++) cur[i] = head[i];
139         int u = s, tail = 0;
140         while(cur[s] != -1)
141         {
142             if(u == t) 
143             {
144                 int tp = INF;
145                 for(int i = tail-1; i >= 0; i--)
146                     tp = min(tp, edge[sta[i]].cap-edge[sta[i]].flow);
147                 maxflow+=tp;
148                 for(int i = tail-1; i >= 0; i--) {
149                     edge[sta[i]].flow+=tp;
150                     edge[sta[i]^1].flow-=tp;
151                     if(edge[sta[i]].cap-edge[sta[i]].flow==0)
152                         tail = i;
153                 }
154                 u = edge[sta[tail]^1].to;
155             }
156             else 
157                 if(cur[u] != -1 && edge[cur[u]].cap > edge[cur[u]].flow && dep[u] + 1 == dep[edge[cur[u]].to]) 
158                 {
159                     sta[tail++] = cur[u];
160                     u = edge[cur[u]].to;
161                 }
162                 else 
163                 {
164                     while(u != s && cur[u] == -1)
165                         u = edge[sta[--tail]^1].to;
166                     cur[u] = edge[cur[u]].next;
167                 }
168         }
169     }
170     return maxflow;
171 }
172 int n,m,a,b;
173 
174 int main()
175 {
176     int t;
177     scanf("%d",&t);
178     while(t--)
179     {
180         init1();
181         scanf("%d%d",&n,&m);
182         for(int i=1;i<=m;++i)
183         {
184             int u,v,c;
185             scanf("%d%d%d",&u,&v,&c);
186             if(u!=v)
187                 addedge1(u,v,c);
188         }
189         scanf("%d%d",&a,&b);
190         Dijkstra(a);
191         memset(vis,false,sizeof(vis));
192         cnt=0;
193         dfs(a);
194         init();
195         for(int i=0;i<cnt;++i)
196             addedge(temp[i].u-1,temp[i].v-1,1);
197         int ans=dinic(a-1,b-1,n);
198         cout<<ans<<endl;
199     }
200     return 0;
201 }

 

posted @ 2015-12-30 20:19  邀月独斟  阅读(297)  评论(0编辑  收藏  举报