hdu3416 判斷最短路是否唯一(每條邊只能走一次)


Marriage Match IV

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


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
 
題意:
有n個城市,m條邊,a到b耗費為c,為單向邊。要求從s到t的最短路徑有多少條,每一條邊只能走一次。
 
思路:
如果每天邊不一定走一次的話,那么可以通過樹形dp來求解。但是這里每條邊只能走一次,也就是說每條路徑上面的邊的流量為1,從起點到終點求一次最大流即可。這樣題目就能夠用最大流來解決。對於建立新的圖,可以先從終點到起點求一次最短路,然后從起點開始dfs,並且維護now[]數組,表示從起點到這個點的路徑長度,
如果now[rt] + dis[t] + edge[i].val == dis[S](dis[]的起點是原本圖中的終點),那么說明這兩個點是最短路上的點,那么可以連邊,流量為1,。跑一次最大流解決問題了。
 

 

#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<string>
#include<time.h>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define INF 1000000001
#define ll long long
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
using namespace std;
const int MAXN = 1010;
struct node
{
    int to;
    int val;
    int next;
}edge[MAXN*100*2],e[MAXN*200*5];
int ind,pre[MAXN],vis[MAXN],dis[MAXN],pre1[MAXN],ind1;
int now[MAXN],S,T;
int n,m;
void add1(int x,int y,int z)
{
    e[ind1].to = y;
    e[ind1].val = z;
    e[ind1].next = pre1[x];
    pre1[x] = ind1 ++;
}
void spfa()
{
    for(int i = 1; i <= n; i++){
        dis[i] = INF;
        vis[i] = 0;
    }
    vis[T] = 1;
    dis[T] = 0;
    queue<int>q;
    q.push(T);
    while(!q.empty()){
        int tp = q.front();
        q.pop();
        vis[tp] = 0;
        for(int i = pre1[tp]; i != -1; i = e[i].next){
            int t = e[i].to;
            if(dis[t] > dis[tp] + e[i].val){
                dis[t] = dis[tp] + e[i].val;
                if(!vis[t]){
                    vis[t] = 1;
                    q.push(t);
                }
            }
        }
    }
}
void add(int x,int y,int z)
{
    edge[ind].to = y;
    edge[ind].val = z;
    edge[ind].next = pre[x];
    pre[x] = ind ++;
}
void dfs1(int rt)
{
    vis[rt] = 1;
    if(rt == T)return ;
    for(int i = pre1[rt]; i != -1; i = e[i].next){
        int t = e[i].to;
        if(now[rt] + dis[t] + e[i].val == dis[S]){
            now[t] = now[rt] + e[i].val;
            add(rt,t,1);
            add(t,rt,0);
            if(!vis[t]){
                dfs1(t);
            }
        }
    }
}
int bfs()
{
    memset(vis,-1,sizeof(vis));
    queue<int>q;
    vis[S] = 0;
    q.push(S);
    while(!q.empty()){
        int tp = q.front();
        q.pop();
        for(int i = pre[tp]; i != -1; i = edge[i].next){
            int t = edge[i].to;
            if(vis[t] == -1 && edge[i].val){
                vis[t] = vis[tp] + 1;
                q.push(t);
            }
        }
    }
    if(vis[T] == -1)return 0;
    return 1;
}
int dfs(int rt,int low)
{
    int used = 0;
    if(rt == T)return low;
    for(int i = pre[rt]; i != -1 && used < low; i = edge[i].next){
        int t = edge[i].to;
        if(vis[t] == vis[rt] + 1 && edge[i].val){
            int a = dfs(t,min(low-used,edge[i].val));
            used += a;
            edge[i].val -= a;
            edge[i^1].val += a;
        }
    }
    if(used == 0)vis[rt] = -1;
    return used;
}
int x[MAXN*100],y[MAXN*100],z[MAXN*100];
void Init(int flag)
{
    ind1 = 0;
    memset(pre1,-1,sizeof(pre1));
    for(int i = 1; i <= m; i++){
        if(!flag){
            add1(y[i],x[i],z[i]);
        }
        else {
            add1(x[i],y[i],z[i]);
        }
    }
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--){
        scanf("%d%d",&n,&m);
        for(int i = 1; i <= m; i++){
            scanf("%d%d%d",&x[i],&y[i],&z[i]);
        }
        Init(0);
        scanf("%d%d",&S,&T);
        spfa();
        Init(1);
        ind = 0;
        memset(now,0,sizeof(now));
        memset(pre,-1,sizeof(pre));
        dfs1(S);
        int ans = 0;
        while(bfs()){
            while(1){
                int a = dfs(S,INF);
                if(!a)break;
                ans += a;
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM