HDU 3416 Marriage Match IV(最短路+最大流)

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有多少条不同的最短路,什么叫做不同的最短路呢,就是任意两条最短路上都没有相同的边,因为是最短路嘛,所以每一条的距离都是相同的、最短的。

这样我们就可以把只要在任意一条最短路上的边加到网络里,然后跑一波最大流,最大的流量就是要求的答案。

那么怎么找到所有最短路上的边呢,我们可以从起点和终点分别跑一次最短路,用dis1[i]表示用起点到i点的最短距离,用dis2[i]表示从终点到i点的最短距离(这里的dis2是反向建边求出的最短距离),那么对于一条边(x,y,z),如果dis1[x] + dis2[y] + z == dis1[B],那么这条边就肯定是某一条最短路上的边。

边建好了就可以跑最大流了。


#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>

using namespace std;
const int maxn = 1100;
const int inf = 1e8;
struct edge
{
    int from, to, cap, flow;
};

struct dinic
{
    int n,m,s,t;
    vector<edge> edges;
    vector<int> g[maxn];
    bool b[maxn];
    int dis[maxn];
    int cur[maxn];

    void initial(int n)
    {
        for(int i=0;i<=n;i++)
            g[i].clear();
        edges.clear();
    }

    void addedge(int from,int to,int cap)
    {
        edges.push_back((edge){from,to,cap,0});
        edges.push_back((edge){to,from,0,0});
        m = edges.size();
        g[from].push_back(m-2);
        g[to].push_back(m-1);
    }

    bool bfs()
    {
        memset(b,0,sizeof(b));
        queue<int> q;
        q.push(s);
        b[s] = 1;
        dis[s] = 0;
        while(!q.empty())
        {
            int x = q.front();
            q.pop();
            for(int i=0;i<g[x].size();i++)
            {
                edge &e = edges[g[x][i]];
                if(!b[e.to] && e.cap > e.flow)
                {
                    b[e.to] = 1;
                    dis[e.to] = dis[x] + 1;
                    q.push(e.to);
                }
            }
        }

        return b[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 = edges[g[x][i]];
            if(dis[x] + 1 == dis[e.to] && (f = dfs(e.to,min(a,e.cap - e.flow)))>0)
            {
                e.flow += f;
                edges[g[x][i]^1].flow -= f;
                flow += f;
                a -= f;
                if(a == 0)
                    break;
            }
        }
        return flow;
    }

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

struct Edge
{
    int to,cost;
    Edge(int a,int b)
    {
        to = a;
        cost = b;
    }
    friend bool operator <(Edge a,Edge b)
    {
        return a.cost > b.cost;
    }
};

int n,m;
int dis1[maxn],dis2[maxn];
vector<Edge> e1[maxn];
vector<Edge> e2[maxn];

void dj(int s,vector<Edge> *e,int *dis)
{
    int i,j;
    priority_queue<Edge> q;
    for(i=1;i<=n;i++)
        dis[i] = inf;
    dis[s] = 0;
    q.push(Edge(s,0));
    while(!q.empty())
    {
        Edge t = q.top();
        q.pop();
        for(i=0;i<e[t.to].size();i++)
        {
            Edge es = e[t.to][i];
            if(dis[es.to] > dis[t.to] + es.cost)
            {
                dis[es.to] = dis[t.to] + es.cost;
                q.push(Edge(es.to,dis[es.to]));
            }
        }
    }
}
int main(void)
{
    int T,i,j,A,B;
    scanf("%d",&T);
    DC.s = 0;
    while(T--)
    {
        scanf("%d%d",&n,&m);
        DC.t = n+1;
        DC.initial(DC.t);
        for(i=1;i<=n;i++)
        {
            e1[i].clear();
            e2[i].clear();
        }
        for(i=1;i<=m;i++)
        {
            int x,y,z;
            scanf("%d%d%d",&x,&y,&z);
            if(x == y)
                continue;
            e1[x].push_back(Edge(y,z));
            e2[y].push_back(Edge(x,z));
        }
        scanf("%d%d",&A,&B);
        dj(A,e1,dis1);
        dj(B,e2,dis2);
        DC.addedge(DC.s,A,inf);
        for(i=1;i<=n;i++)
        {
            for(j=0;j<e1[i].size();j++)
            {
                int t = e1[i][j].to;
                if(dis1[i] + dis2[t] + e1[i][j].cost == dis1[B])
                {
                    DC.addedge(i,t,1);
                }
            }
        }
        DC.addedge(B,DC.t,inf);
        int ans = DC.maxflow(DC.s,DC.t);
        cout << ans << endl;
    }

    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值