hdu 3416 最短路+网络流(不重叠最短路径计数)

来源:互联网 发布:如何在Mac上登录icloud 编辑:程序博客网 时间:2024/06/04 22:35

Marriage Match IV

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


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
37 81 2 11 3 12 4 13 4 14 5 14 6 15 7 16 7 11 76 71 2 12 3 11 3 33 4 13 5 14 6 15 6 11 62 21 2 11 2 21 2
 

Sample Output
211
 

Author
starvae@HDU
 

Source
HDOJ Monthly Contest – 2010.06.05
 

Recommend
lcy
 

题目要求路径不重叠的最短路路径有多少条。

正确的做法是,做一遍最短路径,把属于最短路径的边加入到新图中,把边的容量设为1(保证每条边只用一次,每条路径只走一遍),在新图上跑一遍最大流算法,最大流量就是答案。只保留属于最短路径的边能保证每次从起点走到终点流量都是属于最短路径的。

刚开始的做法是直接暴力跑网络流Dinic算法,把bfs过程改为spfa,记录最短距离,每次沿着d[u]+w==d[v]的边增广下去,到终点的距离发生改变就停止。这样的做法一直错,因为每次增广后对原图进行了修改,修改过的图到终点的距离可能增大了,但是可能依然对应着是原来的最短路径,只不过多走了逆流(反向边的)的部分而表现的最短距离改变了。所以这种做法并不能确定什么时候停止增广。

#include <iostream>#include <cstdio>#include <cstring>#include <cmath>#include <cctype>#include <string>#include <vector>#include <map>#include <set>#include <vector>#include <queue>#include <stack>using namespace std;const int maxn=1e3+10;const int maxm=2e5+10;const int inf=0x3f3f3f3f;typedef pair<int,int> P;struct Edge{    int v,w,cap,nxt;};int first[maxn],tot;Edge edge[maxm];vector<Edge> g[maxn];int n,m;void addedge(int u, int v, int w, int cap){    edge[tot]=Edge{v,w,cap,first[u]};    first[u]=tot++;    edge[tot]=Edge{u,w,0,first[v]};    first[v]=tot++;}void init(){    tot=0;    memset(first, -1, sizeof(first));    for(int i=0; i<=n; i++) g[i].clear();    for(int i=0; i<m; i++){        int u,v,w;        scanf("%d%d%d", &u, &v,&w);        g[u].push_back(Edge{v,w,0,0});    }}int d[maxn];void dijkstra(int s){    priority_queue<P, vector<P>, greater<P> > que;    memset(d, inf, sizeof(d));    d[s]=0;    que.push(P(0,s));    while(!que.empty()){        P cur=que.top(); que.pop();        int u=cur.second;        if(d[u]<cur.first) continue;        for(int i=0; i<g[u].size(); i++){            int v=g[u][i].v, w=g[u][i].w;            if(d[u]+w<d[v]){                d[v]=d[u]+w;                que.push(P(d[v],v));            }        }    }    for(int i=1; i<=n; i++){        for(int j=0; j<g[i].size(); j++){            int v=g[i][j].v, w=g[i][j].w;            if(d[i]+w==d[v])                addedge(i,v,w,1);        }    }}int que[maxn],head,tail;void bfs(int s){    memset(d, inf, sizeof(d));    head=0,tail=-1;    d[s]=0;    que[++tail]=s;    while(tail+1!=head){        int u=que[head++];        for(int i=first[u]; i!=-1; i=edge[i].nxt){            int v=edge[i].v, cap=edge[i].cap;            if(cap<=0)continue;            if(d[u]+1<d[v]){                d[v]=d[u]+1;                que[++tail]=v;            }        }    }}int cur[maxn];int dfs(int u, int t, int f){    if(u==t) return f;    for(int &i=cur[u]; i!=-1; i=edge[i].nxt){        int v=edge[i].v, w=edge[i].w, cap=edge[i].cap;        if(cap<=0 || d[v]!=d[u]+1) continue;        int tmp=dfs(v, t, min(cap,f));        if(tmp){            edge[i].cap-=tmp;            edge[i^1].cap+=tmp;            return tmp;        }    }    return 0;}int dinic(int s, int t){    int ret=0;    while(true){        bfs(s);        if(d[t]==inf) return ret;        memcpy(cur, first, sizeof(first));        int f=inf;        while((f=dfs(s, t, f))>0){ ret+=f;}    }    return ret;}int main(){int t;cin>>t;while(t--&&cin>>n>>m){        init();        int s,t;        scanf("%d%d", &s, &t);        dijkstra(s);        int ans=dinic(s,t);        cout<<ans<<endl;}    return 0;}




0 0
原创粉丝点击