hdu3416 最短路+最大流

题目链接在这里

题目描述

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
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点,每次都要走最短路,且每条最短路的边不能重复,问有多少条这样的路。

首先算出来A点到每点的最短路dis1,然后再算出来B点到每点的最短路dis2,然后遍历每一条边,如果dis1[edge.u] + dis2[edge.v] + edge.w == dis1[B],那么就把这条边加入到最大流的计算边中去。然后通过sap算法计算从A点到B点的最大流。

 

第一次写最大流题。。。。看了好半天

AC代码:

#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
const int MaxN = 100010;
const int MaxM = 5e5 + 10;
const int INF = 0x3f3f3f3f;
struct EdgeFlow{
    int v, flow, cap, nxt;
}edge_flow[MaxM];

struct Edge{
    int v, w;
};
vector G[MaxN];
int dis[MaxN], dis1[MaxN], dis2[MaxN];
int tol, par[MaxN];
int cur[MaxN], gap[MaxN], dep[MaxN], pre[MaxN];
int a[MaxN], b[MaxN], c[MaxN];
int n, m;

inline void addEdge1(int u, int v, int w){
    G[u].push_back(Edge{v, w});
}

void addEdge2(int u, int v, int w, int rw = 0){
    edge_flow[tol].v = v;
    edge_flow[tol].cap = w;
    edge_flow[tol].flow = 0;
    edge_flow[tol].nxt = par[u];
    par[u] = tol++;

    edge_flow[tol].v = u;
    edge_flow[tol].cap = rw;
    edge_flow[tol].flow = 0;
    edge_flow[tol].nxt = par[v];
    par[v] = tol++;
}

void dijkstra(int st){
    memset(dis, INF, sizeof(dis));
    priority_queue, vector >, greater > > que;
    dis[st] = 0;
    que.push(make_pair(0, st));
    while(!que.empty()){
        pair p = que.top();
        que.pop();
        int u = p.second;
        for(int i = 0; i < G[u].size(); ++i){
            Edge e = G[u][i];
            int v = e.v;
            if(dis[v] > dis[u] + e.w){
                dis[v] = dis[u] + e.w;
                que.push(make_pair(dis[v], v));
            }
        }
    }
}

int sap(int st, int ed){
    int N = n;
    memset(gap, 0, sizeof(gap));
    memset(dep, 0, sizeof(dep));
    memset(cur, 0, sizeof(cur));
    int u = st;
    pre[u] = -1;
    gap[0] = N;
    int ans = 0;
    while(dep[st] < N){
        if(u == ed){
            int Min = INF;
            for(int i = pre[u]; i != -1; i = pre[edge_flow[i ^ 1].v])
                if(Min > edge_flow[i].cap - edge_flow[i].flow)
                    Min = edge_flow[i].cap - edge_flow[i].flow;
            for(int i = pre[u]; i != -1; i = pre[edge_flow[i ^ 1].v]){
                edge_flow[i].flow += Min;
                edge_flow[i ^ 1].flow -= Min;
            }
            u = st;
            ans += Min;
            continue;
        }
        bool flag = false;
        int v;
        for(int i = cur[u]; i != -1; i = edge_flow[i].nxt){
            v = edge_flow[i].v;
            if(edge_flow[i].cap - edge_flow[i].flow && dep[v] + 1 == dep[u]){
                flag = true;
                cur[u] = pre[v] = i;
                break;
            }
        }
        if(flag){
            u = v;
            continue;
        }
        int Min = N;
        for(int i = par[u]; i != -1; i = edge_flow[i].nxt){
            if(edge_flow[i].cap - edge_flow[i].flow && dep[edge_flow[i].v] < Min){
                Min = dep[edge_flow[i].v];
                cur[u] = i;
            }
        }
        gap[dep[u]]--;
        if(!gap[dep[u]])    return ans;
        dep[u] = Min + 1;
        gap[dep[u]]++;
        if(u != st)
            u =edge_flow[pre[u] ^ 1].v;
    }
    return ans;
}

int main(){
    int T;
    scanf("%d", &T);
    while(T--){
        scanf("%d %d", &n, &m);
        for(int i = 0; i <= n; ++i)
            G[i].clear();
        for(int i = 0; i < m; ++i){
            scanf("%d%d%d", &a[i], &b[i], &c[i]);
            addEdge1(a[i], b[i], c[i]);
        }
        int st, ed;
        scanf("%d%d", &st, &ed);
        dijkstra(st);

        memcpy(dis1, dis, sizeof(dis));

        for(int i = 0; i <= n; ++i)
            G[i].clear();
        for(int i = 0; i < m; ++i)
            addEdge1(b[i], a[i], c[i]);
        dijkstra(ed);

        memcpy(dis2, dis, sizeof(dis));

        tol = 0;
        memset(par, -1, sizeof(par));
        for(int i = 0; i < m; ++i){
            if(a[i] != b[i] && dis1[a[i]] + dis2[b[i]] + c[i] == dis1[ed])
                addEdge2(a[i], b[i], 1);
        }

        printf("%d\n", sap(st, ed));
    }
    return 0;
}

 

你可能感兴趣的:(最短路)