HDU3416 Marriage Match IV —— 最短路径 + 最大流

题目链接:https://vjudge.net/problem/HDU-3416

Marriage Match IV

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 4710    Accepted Submission(s): 1412


Problem Description
Do not sincere non-interference。
Like that show, now starvae also take part in a show, but it take place between city A and B. Starvae is in city A and girls are in city B. Every time starvae can get to city B and make a data with a girl he likes. But there are two problems with it, one is starvae must get to B within least time, it's said that he must take a shortest path. Other is no road can be taken more than once. While the city starvae passed away can been taken more than once. 


So, under a good RP, starvae may have many chances to get to city B. But he don't know how many chances at most he can make a data with the girl he likes . Could you help starvae?
 
Input
The first line is an integer T indicating the case number.(1<=T<=65)
For each case,there are two integer n and m in the first line ( 2<=n<=1000, 0<=m<=100000 ) ,n is the number of the city and m is the number of the roads.

Then follows m line ,each line have three integers a,b,c,(1<=a,b<=n,0<c<=1000)it means there is a road from a to b and it's distance is c, while there may have no road from b to a. There may have a road from a to a,but you can ignore it. If there are two roads from a to b, they are different.

At last is a line with two integer A and B(1<=A,B<=N,A!=B), means the number of city A and city B.
There may be some blank line between each case.
 
Output
Output a line with a integer, means the chances starvae can get at most.
 
Sample Input
3 7 8 1 2 1 1 3 1 2 4 1 3 4 1 4 5 1 4 6 1 5 7 1 6 7 1 1 7 6 7 1 2 1 2 3 1 1 3 3 3 4 1 3 5 1 4 6 1 5 6 1 1 6 2 2 1 2 1 1 2 2 1 2
 
Sample Output
2 1 1
 
Author
starvae@HDU
 
Source

题意:

求有多少条最短路径,要求边不能够重叠(但题目可以有重边,即两个点之间可以有几条边)。

题解:

1.先用spfa算法求出最短路径,并且筛掉那些不在最短路径上的边。

2.构建网络流图:对于在最短路径上的边u-->v,在网络流图中构建一条边 u-->v,且边权为1,表明这条边只能被走一次。

3.以起点为源点,以终点为汇点,求出最大流,即为答案。

代码如下:

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <algorithm>
  5 #include <vector>
  6 #include <cmath>
  7 #include <queue>
  8 #include <stack>
  9 #include <map>
 10 #include <string>
 11 #include <set>
 12 using namespace std;
 13 typedef long long LL;
 14 const int INF = 2e9;
 15 const LL LNF = 9e18;
 16 const int mod = 1e9+7;
 17 const int MAXM = 1e5+10;
 18 const int MAXN = 1e3+10;
 19 
 20 vector<pair<int,int> >son[MAXN];
 21 int dis1[MAXN], dis2[MAXN], dis[MAXN], inq[MAXN];
 22 void spfa(int start, int N)
 23 {
 24     memset(inq, 0, sizeof(inq));
 25     for(int i = 1; i<=N; i++)
 26         dis[i] = INF;
 27 
 28     queue<int>Q;
 29     Q.push(start);
 30     inq[start] = 1;
 31     dis[start] = 0;
 32     while(!Q.empty())
 33     {
 34         int u = Q.front();
 35         Q.pop(); inq[u] = 0;
 36         for(int i = 0; i<son[u].size(); i++)
 37         {
 38             int v = son[u][i].first;
 39             int w = son[u][i].second;
 40             if(dis[v]>dis[u]+w)
 41             {
 42                 dis[v] = dis[u]+w;
 43                 if(!inq[v])
 44                 {
 45                     Q.push(v);
 46                     inq[v] = 1;
 47                 }
 48             }
 49         }
 50     }
 51 }
 52 
 53 struct Edge
 54 {
 55     int to, next, cap, flow;
 56 }edge[MAXM<<2];
 57 int tot, head[MAXN];
 58 int gap[MAXN], dep[MAXN], pre[MAXN], cur[MAXN];
 59 
 60 void init()
 61 {
 62     tot = 0;
 63     memset(head, -1, sizeof(head));
 64 }
 65 
 66 void add(int u, int v, int w)
 67 {
 68     edge[tot].to = v; edge[tot].cap = w; edge[tot].flow = 0;
 69     edge[tot].next = head[u]; head[u] = tot++;
 70     edge[tot].to = u; edge[tot].cap = 0; edge[tot].flow = 0;
 71     edge[tot].next = head[v]; head[v] = tot++;
 72 }
 73 
 74 int sap(int start, int end, int nodenum)
 75 {
 76     memset(dep, 0, sizeof(dep));
 77     memset(gap, 0, sizeof(gap));
 78     memcpy(cur, head, sizeof(head));
 79     int u = pre[start] = start, maxflow = 0,aug = INF;
 80     gap[0] = nodenum;
 81     while(dep[start]<nodenum)
 82     {
 83         loop:
 84         for(int i = cur[u]; i!=-1; i = edge[i].next)
 85         {
 86             int v = edge[i].to;
 87             if(edge[i].cap-edge[i].flow && dep[u]==dep[v]+1)
 88             {
 89                 aug = min(aug, edge[i].cap-edge[i].flow);
 90                 pre[v] = u;
 91                 cur[u] = i;
 92                 u = v;
 93                 if(v==end)
 94                 {
 95                     maxflow += aug;
 96                     for(u = pre[u]; v!=start; v = u,u = pre[u])
 97                     {
 98                         edge[cur[u]].flow += aug;
 99                         edge[cur[u]^1].flow -= aug;
100                     }
101                     aug = INF;
102                 }
103                 goto loop;
104             }
105         }
106         int mindis = nodenum;
107         for(int i = head[u]; i!=-1; i = edge[i].next)
108         {
109             int v=edge[i].to;
110             if(edge[i].cap-edge[i].flow && mindis>dep[v])
111             {
112                 cur[u] = i;
113                 mindis = dep[v];
114             }
115         }
116         if((--gap[dep[u]])==0)break;
117         gap[dep[u]=mindis+1]++;
118         u = pre[u];
119     }
120     return maxflow;
121 }
122 
123 int u[MAXM], v[MAXM], w[MAXM];
124 int main()
125 {
126     int T, n, m;
127     scanf("%d", &T);
128     while(T--)
129     {
130         int start, end;
131         scanf("%d%d", &n,&m);
132         for(int i = 1; i<=m; i++)
133             scanf("%d%d%d", &u[i], &v[i], &w[i]);
134         scanf("%d%d", &start, &end);
135 
136         for(int i = 1; i<=n; i++) son[i].clear();
137         for(int i = 1; i<=m; i++) son[u[i]].push_back(make_pair(v[i], w[i]));
138         spfa(start, n);
139         memcpy(dis1, dis, sizeof(dis1));
140         int distance = dis1[end];
141 
142         for(int i = 1; i<=n; i++) son[i].clear();
143         for(int i = 1; i<=m; i++) son[v[i]].push_back(make_pair(u[i], w[i]));
144         spfa(end, n);
145         memcpy(dis2, dis, sizeof(dis2));
146 
147         init();
148         for(int i = 1; i<=m; i++)
149             if(dis1[u[i]]+w[i]+dis2[v[i]]==distance)
150                 add(u[i], v[i], 1);
151 
152         int ans = sap(start, end, n);
153         printf("%d
", ans);
154     }
155 }
View Code
原文地址:https://www.cnblogs.com/DOLFAMINGO/p/8150715.html