HDU 3416 Marriage Match IV (求最短路的条数,最大流) Marriage Match IV
题目链接:
http://acm.hust.edu.cn/vjudge/contest/122685#problem/Q
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,0Output
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 76 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
</big>
##Sample Output
<big>
2
1
1
</big>
##Hint
<big>
</big>
<br/>
##题意:
<big>
求最短路的条数.
要求这些路径互相没有相同的边.
</big>
<br/>
##题解:
<big>
由于要求同一条边不能出现在两条最短路中.
所以直接标记出最短路中的边,对这些边跑一次最大流即可. (这里直接用了sap模版)
<br/>
若这个题没有不共边的要求,就直接对最短路中的边dfs即可.
[HDU1142-A Walk Through the Forest](http://acm.hdu.edu.cn/showproblem.php?pid=1142)
题解:http://www.cnblogs.com/Sunshine-tcf/p/5752205.html
</big>
<br/>
##代码:
``` cpp
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <queue>
#include <map>
#include <set>
#include <vector>
#define LL long long
#define eps 1e-8
#define maxn 501000
#define mod 1000000007
#define inf 0x3f3f3f3f
#define IN freopen("in.txt","r",stdin);
using namespace std;
int n, m;
typedef pair<int,int> pii;
priority_queue<pii,vector<pii>,greater<pii> > q;
bool vis[maxn];
int edges, u[maxn], v[maxn], w[maxn];
int first[maxn], _next[maxn];
int dist[maxn];
int pre1[maxn];
void add_edge(int s, int t, int val) {
u[edges] = s; v[edges] = t; w[edges] = val;
_next[edges] = first[s];
first[s] = edges++;
}
void dijkstra(int s) {
memset(pre1, -1, sizeof(pre1));
memset(vis, 0, sizeof(vis));
for(int i=1; i<=n; i++) dist[i]=inf; dist[s] = 0;
while(!q.empty()) q.pop();
q.push(make_pair(dist[s], s));
while(!q.empty()) {
pii cur = q.top(); q.pop();
int p = cur.second;
if(vis[p]) continue; vis[p] = 1;
for(int e=first[p]; e!=-1; e=_next[e]) if(dist[v[e]] > dist[p]+w[e]){
dist[v[e]] = dist[p] + w[e];
q.push(make_pair(dist[v[e]], v[e]));
pre1[v[e]] = p;
}
}
}
//最大流SAP
struct Node {
int to,_next,cap;
}edge[maxn];
int tol;
int head[maxn];
int gap[maxn],dis[maxn],pre[maxn],cur[maxn];
void init() {
tol=0;
memset(head,-1,sizeof(head));
}
void addedge(int u,int v,int w,int rw=0) {
edge[tol].to=v;edge[tol].cap=w;edge[tol]._next=head[u];head[u]=tol++;
edge[tol].to=u;edge[tol].cap=rw;edge[tol]._next=head[v];head[v]=tol++;
}
int sap(int start,int end,int nodenum)
{
memset(dis,0,sizeof(dis));
memset(gap,0,sizeof(gap));
memcpy(cur,head,sizeof(head));
int u=pre[start]=start,maxflow=0,aug=-1;
gap[0]=nodenum;
while(dis[start]<nodenum)
{
loop:
for(int &i=cur[u];i!=-1;i=edge[i]._next)
{
int v=edge[i].to;
if(edge[i].cap&&dis[u]==dis[v]+1)
{
if(aug==-1||aug>edge[i].cap)
aug=edge[i].cap;
pre[v]=u;
u=v;
if(v==end)
{
maxflow+=aug;
for(u=pre[u];v!=start;v=u,u=pre[u])
{
edge[cur[u]].cap-=aug;
edge[cur[u]^1].cap+=aug;
}
aug=-1;
}
goto loop;
}
}
int mindis=nodenum;
for(int i=head[u];i!=-1;i=edge[i]._next)
{
int v=edge[i].to;
if(edge[i].cap&&mindis>dis[v])
{
cur[u]=i;
mindis=dis[v];
}
}
if((--gap[dis[u]])==0)break;
gap[dis[u]=mindis+1]++;
u=pre[u];
}
return maxflow;
}
int main(void)
{
//IN;
int t; cin >> t; int ca = 1;
while(t--)
{
memset(first, -1, sizeof(first)); edges = 0;
cin >> n >> m;
while(m--) {
int u,v,w; scanf("%d %d %d", &u, &v, &w);
if(u == v) continue;
add_edge(u, v, w);
}
int s, t; cin >> s >> t;
dijkstra(s);
init();
for(int e=0; e<edges; e++) {
//判断是否是最短路上的边
if(dist[v[e]] == dist[u[e]]+w[e]) {
addedge(u[e], v[e], 1);
}
}
int paths = sap(s, t, n);
printf("%d
", paths);
}
return 0;
}