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,0

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

</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;
}
原文地址:https://www.cnblogs.com/Sunshine-tcf/p/5752180.html