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;

}



你可能感兴趣的:(poj)