hdu3987,最小割时求最少割边数

题意:求最小割时候割边最少的数量。算法:先求dinic一遍,跑出残网络,再把该网络中满流量(残量为0)的边
残量改为1,其他边残量改为无穷,则再跑一次最大流,所得即为答案。(思,最小割有喝多组,但是要割边数量最少
的,那么把满流的流量改为1,再跑一次最大流即可)。
未1A原因:
1*:添加边的时候,把双向边添加为一条(反向的流量上限==正向),这样不是不可以,但是由于后面用到要取有效边
(非后悔边,边编号比为偶数),导致错误,改为添加俩次即可。

2//:数据较大,总流量10W*1000,可能暴int。


#include<iostream>  //98ms
#include<cstdio>
#include<queue>
using namespace std;
long long e[400001][3];int head[1100];const int inf=0x3f3f3f3f;
int n,m;int nume;
void addedge(int from,int to,int w,int derect)  //添加边的函数,derect为1时要添加双向边
{
    e[nume][0]=to; e[nume][1]=head[from];head[from]=nume;
    e[nume++][2]=w;
    e[nume][0]=from; e[nume][1]=head[to];head[to]=nume;
    e[nume++][2]=0;
    if(derect==1)
   {
    e[nume][0]=from; e[nume][1]=head[to];head[to]=nume;
    e[nume++][2]=w;
    e[nume][0]=to; e[nume][1]=head[from];head[from]=nume;
    e[nume++][2]=0;
   }
}
int level[1100];int vis[1100];
bool bfs()                 //dinic
{
    for(int i=0;i<=n;i++)
      vis[i]=level[i]=0;
    queue<int>q;q.push(0);
    vis[0]=1;
    while(!q.empty())
    {
        int cur=q.front();q.pop();
        for(int i=head[cur];i!=-1;i=e[i][1])
        {    int v=e[i][0];
             if(!vis[v]&&e[i][2]>0)
             {
                 level[v]=level[cur]+1;
                 if(v==n-1)return 1;
                 vis[v]=1;
                 q.push(v);
             }
        }
    }
    return vis[n-1];
}
long long dfs(int u,long long minf)
{
    if(u==n-1||minf==0)return minf;
    long long sumf=0,f;
    for(int i=head[u];i!=-1&&minf;i=e[i][1])
    {    int v=e[i][0];
        if(level[v]==level[u]+1&&e[i][2]>0)
       {
           f=dfs(v,minf<e[i][2]?minf:e[i][2]);
           e[i][2]-=f;e[i^1][2]+=f;
           minf-=f;sumf+=f;
       }
    }
    return sumf;
}
long long dinic()
{
    long long sum=0;
    while(bfs())
    {
        sum+=dfs(0,inf);
    }
    return sum;
}
long long getmincut()     
{
    long long cutedge=0;
    for(int i=0;i<=n;i++)
      vis[i]=0;
    queue<int>q;q.push(0);vis[0]=1;
    while(!q.empty())
    {
        int cur=q.front();q.pop();
        for(int i=head[cur];i!=-1;i=e[i][1])
        {    int v=e[i][0];
              if(i%2==0&&e[i][2]==0)             //边数偶数的边是残量网络有效边(非后悔边)
                { e[i][2]=1;e[i^1][2]=0;}
            else if(i%2==0&&e[i][2]>0)
                {e[i][2]=inf;e[i^1][2]=0;}
             if(!vis[v]&&e[i][2]>=0)
             {
                     vis[v]=1;q.push(v);
             }
        }
    }
    cutedge=dinic();
    return cutedge;
}
int main()
{
    int N;scanf("%d",&N); int casenum=1;
    while(N--)
    {
       scanf("%d%d",&n,&m);
       nume=0;
      for(int i=0;i<=n;i++)
       head[i]=-1;
       for(int i=0;i<m;i++)
       {    int from,to,w,d;
         scanf("%d%d%d%d",&from,&to,&w,&d);
         addedge(from,to,w,d);        
       }
       dinic();
       long long ans=getmincut();
      printf("Case %d: %lld
",casenum,ans);
      casenum++;
    }
    return 0;
}


原文地址:https://www.cnblogs.com/yezekun/p/3925805.html