zoukankan      html  css  js  c++  java
  • (中等) HDU 3416 Marriage Match IV,SPFA+SAP。

      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?
        
      题意就是求在最短路的基础上有几条路可以到达,但是每条路之间边彼此不能重合。。。
      然后就是先求出最短路来,然后把所以 lowcost[v]==lowcost[u]+cost[u][v] 的边留下,然后再求最大流就好了。。。。。。
     
    代码如下:
    #include <stdio.h>
    #include <string.h>
    #include <iostream>
    #include <algorithm>
    #include <vector>
    #include <queue>
    #include <set>
    #include <map>
    #include <string>
    #include <math.h>
    #include <stdlib.h>
    #include <time.h>
        
    using namespace std;
    
    const int MaxN=5010;
    const int MaxM=500005;
    const int INF=10e8;
    
    namespace first
    {
    
    struct Edge
    {
        int to,next,cost;
    };
    
    Edge E[MaxM];
    int head[MaxN],Ecou;
    int vis[MaxN];
    
    void init(int N)
    {
        Ecou=0;
    
        for(int i=1;i<=N;++i)
        {
            head[i]=-1;
            vis[i]=0;
        }
    }
    
    void addEdge(int u,int v,int c)
    {
        E[Ecou].to=v;
        E[Ecou].cost=c;
        E[Ecou].next=head[u];
        head[u]=Ecou++;
    }
    
    void SPFA(int lowcost[],int N,int start)
    {
        queue <int> que;
        int u,v,c;
    
        for(int i=1;i<=N;++i)
            lowcost[i]=INF;
        lowcost[start]=0;
    
        que.push(start);
        vis[start]=1;
    
        while(!que.empty())
        {
            u=que.front();
            que.pop();
    
            vis[u]=0;
    
            for(int i=head[u];i!=-1;i=E[i].next)
            {
                v=E[i].to;
                c=E[i].cost;
    
                if(lowcost[v]>lowcost[u]+c)
                {
                    lowcost[v]=lowcost[u]+c;
    
                    if(!vis[v])
                    {
                        que.push(v);
                        vis[v]=1;
                    }
                }
            }
        }
    }
    
    }
    
    namespace second
    {
    
    struct Edge
    {
        int to,next,cap,flow;
    };
    
    Edge E[MaxM];
    int Ecou,head[MaxN];
    int gap[MaxN],dis[MaxN],pre[MaxN],cur[MaxN];
    int S,T;
    
    void init(int N,int _S,int _T)
    {
        S=_S;
        T=_T;
        Ecou=0;
    
        for(int i=1;i<=N;++i)
        {
            head[i]=-1;
            gap[i]=dis[i]=0;
        }
    }
    
    void addEdge(int u,int v,int c,int rc=0)
    {
        E[Ecou].to=v;
        E[Ecou].cap=c;
        E[Ecou].flow=0;
        E[Ecou].next=head[u];
        head[u]=Ecou++;
    
        E[Ecou].to=u;
        E[Ecou].cap=rc;
        E[Ecou].flow=0;
        E[Ecou].next=head[v];
        head[v]=Ecou++;
    }
    
    void update(int remm)
    {
        int u=T;
    
        while(u!=S)
        {
            E[pre[u]].flow+=remm;
            E[pre[u]^1].flow-=remm;
            u=E[pre[u]^1].to;
        }
    }
    
    int SAP(int N)
    {
        for(int i=1;i<=N;++i)
            cur[i]=head[i];
    
        int u,v,ret=0,remm=INF,mindis;
    
        u=S;
        pre[S]=-1;
        gap[0]=N;
    
        while(dis[S]<N)
        {
            loop:
            for(int i=cur[u];i!=-1;i=E[i].next)
            {
                v=E[i].to;
                
                if(E[i].cap-E[i].flow && dis[u]==dis[v]+1)
                {
                    pre[v]=i;
                    cur[u]=i;
                    u=v;
    
                    if(u==T)
                    {
                        for(int i=pre[u];i!=-1;i=pre[E[i^1].to])
                            remm=min(remm,E[i].cap-E[i].flow);
    
                        ret+=remm;
                        update(remm);
                        u=S;
                        remm=INF;
                    }
    
                    goto loop;
                }
            }
    
            mindis=N-1;
            for(int i=head[u];i!=-1;i=E[i].next)
                if(E[i].cap-E[i].flow && mindis>dis[E[i].to])
                {
                    cur[u]=i;
                    mindis=dis[E[i].to];
                }
    
            if(--gap[dis[u]]==0)
                break;
    
            dis[u]=mindis+1;
    
            ++gap[dis[u]];
    
            if(u!=S)
                u=E[pre[u]^1].to;
        }
    
        return ret;
    }
    
    }
    
    int lowcost[MaxN];
    
    int main()
    {
        //freopen("in.txt","r",stdin);
        //freopen("out.txt","w",stdout);
        
        int T;
        int N,M;
        int A,B;
        int a,b,c;
    
        scanf("%d",&T);
    
        while(T--)
        {
            scanf("%d %d",&N,&M);
    
            first::init(N);
    
            {
                using namespace first;
    
                while(M--)
                {
                    scanf("%d %d %d",&a,&b,&c);
    
                    addEdge(a,b,c);
                }
    
                scanf("%d %d",&A,&B);
    
                SPFA(lowcost,N,A);
    
                second::init(N,A,B);
    
                for(int u=1;u<=N;++u)
                    for(int i=head[u];i!=-1;i=E[i].next)
                        if(lowcost[E[i].to]==lowcost[u]+E[i].cost)
                            second::addEdge(u,E[i].to,1);
            }
    
            {
                using namespace second;
    
                printf("%d
    ",SAP(N));
            }
        }
    
        return 0;
    }
    View Code
  • 相关阅读:
    linux下查看当前登陆的用户数目
    uboot能ping通本机无法ping通本机上搭建的虚拟机
    一个时序图描述从用户在浏览器地址栏输入url并按回车,到浏览器显示相关内容的各个过程
    3*0.1 == 0.3 将会返回什么?true 还是 false?
    Floating Point Math
    浮点数在计算机中是如何表示的
    浮点数在计算机中是如何表示的
    Java并发编程:volatile关键字解析
    join的源码
    i++ 是线程安全的吗
  • 原文地址:https://www.cnblogs.com/whywhy/p/4338403.html
Copyright © 2011-2022 走看看