acdream 1017 Fast Transportation(层次图)

题目链接:http://www.acdream.net/problem.php?id=1017

题意:给定一个无向图,要用最少的时间从源点S向终点T运送K件货物。要求:

(1)从一个节点走到相邻节点用时1天;

(2)一天中一条路只能使用一次。

思路:对于最后要求的最短时间,由于单调性,可以使用二分答案的策略。对于每次枚举的天数S,将图中的每个点都拆成S个,则全图变成S层,规定同层之间不允许连边,对于原始图中的边(i,j),则在相邻两层中将对应的点从低的一层连上高的一层。设置超级源点,向第一层中的出发点连上一条容量为K的边,将每层中的目的地点向超级汇点连上一条容量无穷的边,然后求最大流是否等于K。

 

#include <iostream>

#include <stdio.h>

#include <string.h>

using namespace std;



 struct Node

 {

     int v,cap,next;



     Node(){}

     Node(int _v,int _cap,int _next)

     {

         v=_v;

         cap=_cap;

         next=_next;

     }

 };





 const int INF=1000000000;

 const int M=100005;

 int num[M],h[M],curedge[M],pre[M];

 int Queue[M];

 Node edges[1200005];

 int n,m,s,t,head[M],e;





 void Add(int u,int v,int cap)

 {

     edges[e]=Node(v,cap,head[u]);

     head[u]=e++;

     edges[e]=Node(u,0,head[v]);

     head[v]=e++;

 }







 void BFS(int s,int t)

 {

     memset(num,0,sizeof(num));

     memset(h,-1,sizeof(h));

     num[0]=1;

     int front=0,rear=0;

     h[t]=0;

     Queue[rear++]=t;

     int u,v,i;

     while(front!=rear)

     {

         u=Queue[front++];

         front=front%M;

         for(i=head[u];i!=-1;i=edges[i].next)

         {

             v=edges[i].v;

             if(edges[i].cap!=0||h[v]!=-1) continue;

             Queue[rear++]=v;

             rear=rear%M;

             ++num[h[v]=h[u]+1];

         }

     }

 }



 int Maxflow(int s,int t,int n)

 {

     int ans=0,i,k,x,d,u;



     BFS(s,t);



     for(i=0;i<=n;i++) curedge[i]=head[i];

     num[n]=n;u=s;

     while(h[s]<n)

     {

         if(u==t)

         {

             d=INF+1;

             for(i=s;i!=t;i=edges[curedge[i]].v) if(d>edges[curedge[i]].cap)

                 k=i,d=edges[curedge[i]].cap;

             for(i=s;i!=t;i=edges[curedge[i]].v)

             {

                 x=curedge[i];

                 edges[x].cap-=d;

                 edges[x^1].cap+=d;

             }

             ans+=d;u=k;

         }

         for(i=curedge[u];i!=-1;i=edges[i].next) if(edges[i].cap>0&&h[u]==h[edges[i].v]+1)

             break;

         if(i!=-1)

         {

             curedge[u]=i;

             pre[edges[i].v]=u;

             u=edges[i].v;

         }

         else

         {

             curedge[u]=head[u];

             for(x=n,i=head[u];i!=-1;i=edges[i].next) if(edges[i].cap>0&&h[edges[i].v]<x)

                 x=h[edges[i].v];

             h[u]=x+1;num[h[u]]++;

             if(u!=s) u=pre[u];

         }

     }

     return ans;

 }



int map[65][65];

int K;



int OK(int mid)

{

    int S=0,T=(mid+1)*n+1;

    memset(head,-1,sizeof(head));

    e=0;

    int i,j,k;

    for(i=1;i<=n;i++) for(j=1;j<=n;j++) if(map[i][j])

    {

        for(k=1;k<=mid;k++) Add((k-1)*n+i,k*n+j,1);

    }

    for(i=1;i<=n;i++) for(k=1;k<=mid;k++) Add((k-1)*n+i,k*n+i,INF);

    Add(S,s,K);

    for(k=1;k<=mid;k++) Add(k*n+t,T,INF);

    return Maxflow(S,T,T+2)==K;

}



int main()

{

    while(scanf("%d%d%d%d%d",&n,&m,&K,&s,&t)!=-1)

    {

        memset(map,0,sizeof(map));

        int i,j,u,v;

        for(i=1;i<=m;i++)

        {

            scanf("%d%d",&u,&v);

            map[u][v]=map[v][u]=1;

        }

        int low=1,high=n+K,mid;

        while(low<=high)

        {

            mid=(low+high)>>1;

            if(OK(mid)) high=mid-1;

            else low=mid+1;

        }

        if(high>=1&&OK(high)) printf("%d\n",high);

        else printf("%d\n",low);

    }

    return 0;

}

 

  

 

你可能感兴趣的:(port)