POJ 1459(最大流)

//题目类型:最大流(多源点、多汇点)构图简单题 
//解题思路:分别添加超级源点和超级汇点,使用ISAP算法实现,另外本题的输入与输出也应该特别学习 
#include <iostream>
#include <queue>
//#include <conio.h>
using namespace std;
#define arraysize 205
int maxData = 0x7fffffff;
int capacity[arraysize][arraysize];     //残留网络,初始化为原图  
int pre[arraysize];                     //前驱 
int num[arraysize];                     //num[i]表示标号为i的顶点数有多少
int d[arraysize];                       //各结点的标号 
int n,np,nc,m;                          
void init(int src,int des)              //BFS计算标号,汇点t标号为0
{
     int i,j;
     queue<int> myqueue;
     myqueue.push(des);
     memset(num,0,sizeof(num));
     //memset(d,1,sizeof(d));
     for(i=0;i<n+2;++i)      //其余点的距离标号为无穷大 
        d[i] = maxData;
     d[des] = 0;             //汇点的距离标号为0 
     num[0] = 1;
     int frontint;
     while(!myqueue.empty())  
     {
         frontint = myqueue.front();myqueue.pop();
         for(i=0;i<n+2;++i)
         {
             if(d[i]>=n+2 && capacity[i][frontint]>0)   //此处要特别注意,通过frontint的值改变其他的距离标号 
             {
                 d[i] = d[frontint]+1;
                 myqueue.push(i);  
                 num[d[i]]++;     
             }                  
         }
     }
}
int findarc(int t)              //查找允许弧 
{
    int i,j;
    for(i=0;i<n+2;++i)
    {
        if(capacity[t][i]>0 && d[t]==d[i]+1) return i;
    }
    return -1;
}
int relabel(int t)              //重新标号 
{
    int i,j;
    //int mm = INT_MAX;
    int mm = maxData;
    for(i=0;i<n+2;++i)
    {
        if(capacity[t][i]>0) mm = min(mm,d[i]+1); 
    }
    return mm==maxData?(n+2):mm;
}
int maxFlow(int src,int des)
{
    int sumflow = 0;
    int delta;
    int i=src;      //初始化为源点 
    int j;
    memset(pre,-1,sizeof(pre));    
    while(d[src]<n+2)
    {
       j = findarc(i);
       if(j>=0)
       {
           pre[j] = i;
           i = j;            //从前往后找 
           if(i==des)        //找到了增广路径  
           {
               delta = maxData;
               for (i=des;i!=src;i=pre[i]) delta=min(delta,capacity[pre[i]][i]);  //求的增广路径的可增流量  
               for (i=des;i!=src;i=pre[i]) capacity[pre[i]][i] -= delta, capacity[i][pre[i]] += delta; //修改残留网络 
               sumflow += delta;
           }
       }
       else
       {
           int x = relabel(i);
           num[x]++;
           num[d[i]]--;
           if(num[d[i]]==0) return sumflow;    //间隙优化 
           d[i] = x;
           if(i!=src) i =pre[i];           
       }
    }
    return sumflow;
}
int main()
{
    //freopen("1.txt","r",stdin);
    int i,j;
    int start,end,weight;
    char tempchar;
    //本题的输入输出要特别注意 
    while(cin>>n>>np>>nc>>m)
    {
        memset(capacity,0,sizeof(capacity));
        //定义一个字符类型来处理题目中的括号 
        for(i=0;i<m;++i)
        {
            cin>>tempchar>>start>>tempchar>>end>>tempchar>>weight;
            capacity[start][end] = weight;            
        }
        for(i=0;i<np;++i)
        {
            cin>>tempchar>>end>>tempchar>>weight;
            capacity[n+1][end]= weight;          //n+1代表超级源点            
        }
        for(i=0;i<nc;++i)
        {
            cin>>tempchar>>start>>tempchar>>weight;
            capacity[start][n]= weight;            //n代表超级终点 
        }
        init(n+1,n);            //初始化标号 
        int result = maxFlow(n+1,n);        // 计算最大流 
        cout<<result<<endl;
    }
    /*采取scanf的方式读取 
    while(scanf("%d%d%d%d",&n,&np,&nc,&m)!=EOF)
    {
        memset(r,0,sizeof(r));
        for(i=1;i<=m;i++)
        {
            scanf(" (%d,%d)%d",&a,&b,&z);
            r[a][b]=z;
        }
        for(i=1;i<=np;i++)
        {
            scanf(" (%d)%d",&a,&z);
            r[n][a]=z;
        }
        for(i=1;i<=nc;i++)
        {
            scanf(" (%d)%d",&a,&z);
            r[a][n+1]=z;
        }
        init(n+1,n);
        printf("%d\n",maxFlow(n+1,n));
    }*/
    //getch();
    return 0;
}

posted @ 2010-05-26 22:33  北海小龙  阅读(582)  评论(0编辑  收藏  举报