您的位置:首页 > 其它

HDU_3416_Marriage Match IV(最短路+最大流)

2015-09-17 09:27 441 查看

Marriage Match IV

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)

Total Submission(s): 2728 Accepted Submission(s): 826


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




题意:有向图中,从起点A走到终点B,每条路只能一次,问最多能走多少次最短路。

分析:最短路+最大流。先用最短路预处理出起点与终点到所有点的最短路,然后对于所有的边(u,v,d)判断一下是否在最短路径上(dis[s][u]+d+dis[t][v]==dis[u][t]),保留下这些有用边,容量都为1,然后跑一遍最大流即可。

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

代码清单:

#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<stack>
#include<cctype>
#include<string>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;

#define end() return 0

typedef long long ll;
typedef unsigned int uint;
typedef unsigned long long ull;

const int maxN = 1000 + 5;
const int maxn = 10000 + 5;
const int maxv = 100000 + 5;
const int INF = 0x7f7f7f7f;

struct Edge{
    int from,to,cap,flow;
    Edge(int u,int v,int c,int f):from(u),to(v),cap(c),flow(f){}
};

struct dinic{
    int n,m,s,t; //结点数,边数(包括反向弧),源点,汇点
    vector<Edge>edge;//边表。edge[e]和edge[e^1]互为反向弧
    vector<int>G[maxn];//邻接表。G[i][j]表示结点i的第j条边在e数组的序号
    bool vis[maxn]; //bfs用
    int d[maxn]; //从起点到i的距离
    int cur[maxn]; //当前弧下标

    void init(int n,int s,int t){
        this -> n = n;
        this -> s = s;
        this -> t = t;
        for(int i=0;i<=n;i++) G[i].clear();
        edge.clear();
    }

    void addEdge(int from,int to,int cap){
        edge.push_back(Edge(from,to,cap,0));
        edge.push_back(Edge(to,from,0,0));
        m=edge.size();
        G[from].push_back(m-2);
        G[to].push_back(m-1);
    }

    bool bfs(){
        memset(vis,false,sizeof(vis));
        queue<int>q;
        q.push(s);
        d[s]=0;
        vis[s]=true;
        while(!q.empty()){
            int x=q.front();q.pop();
            for(int i=0;i<G[x].size();i++){
                Edge& e=edge[G[x][i]];
                if(!vis[e.to]&&e.cap>e.flow){ //只考虑残量网络中的弧
                    vis[e.to]=true;
                    d[e.to]=d[x]+1;
                    q.push(e.to);
                }
            }
        }
        return vis[t];
    }

    int dfs(int x,int a){
        if(x==t||a==0) return a;
        int flow=0,f;
        for(int& i=cur[x];i<G[x].size();i++){ // & -> 从上次考虑的弧
            Edge& e=edge[G[x][i]];
            if(d[x]+1==d[e.to]&&(f=dfs(e.to,min(a,e.cap-e.flow)))>0){
                e.flow+=f;
                edge[G[x][i]^1].flow-=f;
                flow+=f;
                a-=f;
                if(a==0) break;
            }
        }
        return flow;
    }

    int maxflow(){
        int flow=0;
        while(bfs()){
            memset(cur,0,sizeof(cur));
            flow+=dfs(s,INF);
        }
        return flow;
    }
};

struct EDGE{
    int to,dis;
    EDGE(){}
    EDGE(int v,int d):to(v),dis(d){}
};

int T;
int N,M,st,ta;
int A[maxv],B[maxv],C[maxv];
vector<EDGE>graph[maxN];
int dist[2][maxN];
bool vist[maxN];
dinic dc;

void input(){
    scanf("%d%d",&N,&M);
    for(int i=1;i<=N;i++) graph[i].clear();
    for(int i=1;i<=M;i++){
        scanf("%d%d%d",&A[i],&B[i],&C[i]);
        graph[A[i]].push_back(EDGE(B[i],C[i]));
    }
    scanf("%d%d",&st,&ta);
}

void spfa(int s){
    int pose=(s==st)?0:1;
    memset(dist[pose],INF,sizeof(dist[pose]));
    memset(vist,false,sizeof(vist));
    queue<int>q;
    while(!q.empty()) q.pop();
    dist[pose][s]=0;
    vist[s]=true;
    q.push(s);
    while(!q.empty()){
        int p=q.front();q.pop();
        vist[p]=false;
        for(int i=0;i<graph[p].size();i++){
            EDGE& e=graph[p][i];
            if(dist[pose][e.to]>dist[pose][p]+e.dis){
                dist[pose][e.to]=dist[pose][p]+e.dis;
                if(!vist[e.to]){
                    vist[e.to]=true;
                    q.push(e.to);
                }
            }
        }
    }
}

void createGraph(){
    dc.init(N,st,ta);
    for(int i=1;i<=M;i++){
        if(dist[0][A[i]]+dist[1][B[i]]+C[i]==dist[0][ta]){
            dc.addEdge(A[i],B[i],1);
        }
    }
}

void solve(){
    spfa(st);
    for(int i=1;i<=N;i++) graph[i].clear();
    for(int i=1;i<=M;i++) graph[B[i]].push_back(EDGE(A[i],C[i]));
    spfa(ta);
    createGraph();
    printf("%d\n",dc.maxflow());

}

int main(){
    scanf("%d",&T);
    while(T--){
        input();
        solve();
    }end();
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: