最大流问题

给你一个图,图中有多少个顶点、点与点之间的距离(边长)告诉你,求从S点到T点的最大流量是多少?

Sample Input
2
3 2
1 2 1
2 3 1
3 3
1 2 1
2 3 1
1 3 1
 
Sample Output
Case 1: 1
Case 2: 2
 
#include<cstdio>
#include<cstring>
#include<climits>

using namespace std;

#define N 90005
#define M 4000005
#define INF INT_MAX

int s,t,num,pre[N],dis[N],gap[N],head[N],cur[N];

struct node
{
     int u,v,w;
     int next;
}e[M];

inline void add(int u,int v,int w)
{
     e[num].u=u;
     e[num].v=v;
     e[num].w=w;
     e[num].next=head[u];
     head[u]=num++;
}

inline void addedge(int u,int v,int w)
{
     add(u,v,w);
     add(v,u,0);
}

inline int max(int a,int b)
{
    return a>b?a:b;
}

inline int min(int a,int b)
{
    return a<b?a:b;
}

int isap(int s,int t,int n)
{
     int top,mindis,maxflow=0,v,i,aug;
     bool flag;
     for(i=0;i<=n;i++)
     {
         cur[i]=head[i];
         gap[i]=dis[i]=0;
     }
     top=pre[s]=s;
     aug=INF;

     while(dis[s]<n)
     {
         flag=0;
         for(i=cur[top];i!=-1;i=e[i].next)
         {
             v=e[i].v;
             if(e[i].w>0&&dis[top]==dis[v]+1)
             {
                 flag=1;
                break;
             }
         }
         if(flag)
         {
             pre[v]=top;
             cur[top]=i;
             aug=min(aug,e[i].w);
             top=v;
             if(top==t)
             {
                 while(top!=s)
                 {
                     top=pre[top];
                     e[cur[top]].w-=aug;
                     e[cur[top]^1].w+=aug;
                 }
                 top=s;
                 maxflow+=aug;
                 aug=INF;
             }
         }
         else
         {
             if(--gap[dis[top]]==0)
                break;
              mindis=n;
             cur[top]=head[top];
             for(i=head[top];i!=-1;i=e[i].next)
             {
                 v=e[i].v;
                 if(e[i].w>0&&dis[v]+1<mindis)
                 {
                     mindis=dis[v]+1;
                     cur[top]=i;
                 }
             }
             dis[top]=mindis;
             gap[mindis]++;
             if(top!=s)
                 top=pre[top];
         }
     }
     return maxflow;
}

void init()
{
     num=0;
     memset(head,-1,sizeof(head));
}

int main()
{
     int nodenum,m,n,test;
     scanf("%d",&test);
     for(int ii=1;ii<=test;ii++)
     {
         scanf("%d%d",&n,&m);
         init();
         while(m--)
         {
             int u,v,w;
             scanf("%d%d%d",&u,&v,&w);
             addedge(u,v,w);

         }
        //source=1,sink=n,nodenum=n;
         int res=isap(1,n,n);
         printf("Case %d: %d\n",ii,res);
     }
     return 0;
}

  另一种方法:

 #include <iostream>
 #include <queue>
  using namespace std;
  
  const int N = 210;
  const int INF = 0x7FFFFFFF;
  int n,m,map[N][N],path[N],flow[N],start,end;
  queue<int> q;
  
int bfs(){
     int i,t;
     while(!q.empty()) q.pop();
     memset(path,-1,sizeof(path));
     path[start]=0,flow[start]=INF;
     q.push(start);
     while(!q.empty()){
         t=q.front();
        q.pop();
        if(t==end) break;
        for(i=1;i<=m;i++){
             if(i!=start && path[i]==-1 && map[t][i]){
                 flow[i]=flow[t]<map[t][i]?flow[t]:map[t][i];
                 q.push(i);
                path[i]=t;
             }
         }
     }
     if(path[end]==-1) return -1;
     return flow[m];                   //一次遍历之后的流量增量
 }
 int Edmonds_Karp(){
     int max_flow=0,step,now,pre;
     while((step=bfs())!=-1){          //找不到增路径时退出
         max_flow+=step;
         now=end;
         while(now!=start){
             pre=path[now];
             map[pre][now]-=step;      //更新正向边的实际容量
             map[now][pre]+=step;      //添加反向边
             now=pre;
         }
     }
     return max_flow;
 }
 int main(){
     int i,u,v,cost;
     while(scanf("%d %d",&m,&n)!=EOF){
		 if(!n&&!m)
			 return 0 ;
         memset(map,0,sizeof(map));
         for(i=0;i<n;i++){
             scanf("%d %d %d",&u,&v,&cost);
             map[u][v]+=cost;           //not just only one input
         }
         start=1,end=m;
		 printf("%d\n",Edmonds_Karp());
     }
     return 0;
 }

  

posted @ 2014-04-03 09:00  NYNU_ACM  阅读(125)  评论(0编辑  收藏  举报