hdu 2435 dinic算法模板+最小割性质

时间:2021-09-03 04:25:22
#include<stdio.h>
#include<queue>
#include<string.h>
using namespace std;
#define inf 0x3fffffff
#define N 200
struct node {
int v,w,next;
}bian[N*N*2],fbian[N*N*2];
int head[N],yong,tt;
int  deep[N];//深度保留层次图
void addedge(int u,int v,int w) {
bian[yong].v=v;
bian[yong].w=w;
bian[yong].next=head[u];
head[u]=yong++;
}
int bfs(int s) {//寻找层次图
  int i,cur;
  queue<int>q;
  memset(deep,-1,sizeof(deep));
  q.push(s);
  deep[s]=1;
  while(!q.empty()) {
    cur=q.front();
    q.pop();
    for(i=head[cur];i!=-1;i=bian[i].next)
        if(bian[i].w&&deep[bian[i].v]==-1) {
            deep[bian[i].v]=deep[cur]+1;
            q.push(bian[i].v);
        }
  }
  if(deep[tt]!=-1)return 1;
  return 0;
}
int Min(int a,int b) {
return a>b?b:a;
}
int dfs(int s,int limit) {//多次dfs
    int i,cost=0,flow,v;
   // printf("%d %d\n",s,head[s]);
    if(s==tt) {return limit;}
    for(i=head[s];i!=-1;i=bian[i].next) {
        v=bian[i].v;
      //  printf("%d %d %d\n",s,v,bian[i].w);
        if(bian[i].w&&deep[v]==deep[s]+1) {
             //   printf("%d\n",v);
            flow=dfs(v,Min(limit-cost,bian[i].w));
            if(flow>0) {
                bian[i].w-=flow;
                bian[i^1].w+=flow;
                cost+=flow;
                if(limit==cost)break;
            }
            else
                deep[v]=-1;//如果再次遇到v就不会进行下去
        }
    }
    return cost ;
}
int dinic_maxflow(int s) {//dinic算法模板
  int sum=0;
while(bfs(1)) {
//for(i=1;i<=tt;i++)
 //  printf("%d\n",deep[i]);
    sum+=dfs(1,inf);
}
  return sum;
}
/*int visit[N];
void dfs1(int u) {
  int i;
  visit[u]=1;
  for(i=head[u];i!=-1;i=bian[i].next) {
    if(bian[i].w&&visit[bian[i].v]==0)
    dfs1(bian[i].v);
  }
}*/
int ds[N],dds,dt[N],ddt;
int fhead[N],fyong;
int main() {
       int t,m,n,i,j,k,maxflow,ma,fma,fa,fb;
       scanf("%d",&t);
       while(t--) {
        scanf("%d%d",&n,&m);
        yong=0;
        memset(head,-1,sizeof(head));
        while(m--) {
            scanf("%d%d%d",&i,&j,&k);
            addedge(i,j,k);//加入边
            addedge(j,i,0);//退边
        }
        tt=n;
        maxflow=dinic_maxflow(1);//最大流模板
      dds=0;ddt=0;
    /*  memset(visit,0,sizeof(visit));
      dfs1(1);*/
      for(i=2;i<n;i++) {//根据deep是否为-1可以得到源点集和汇点集
        if(deep[i]!=-1)//源点集
            ds[++dds]=i;
        else
            dt[++ddt]=i;//汇点集
      }
     // printf("%d %d\n",dds,ddt);
    /* for(i=2;i<n;i++) {
        if(visit[i])
            ds[++dds]=i;
        else
            dt[++ddt]=i;
     }*/
        for(i=0;i<yong;i++)//保留残留网络
            fbian[i]=bian[i];
            for(i=1;i<=n;i++)//保留残留网络
                fhead[i]=head[i];
            ma=0;
            fyong=yong;//保留残留网络
            for(i=1;i<=dds;i++)//枚举
                for(j=1;j<=ddt;j++) {
                    fa=ds[i];fb=dt[j];
                    for(k=0;k<yong;k++)//加入了新边,必须跟新为原来的求最大流一次的残留网络
                        bian[k]=fbian[k];
            memset(head,0,sizeof(head));
            for(k=1;k<=n;k++) //因为加入了新边,所以必须跟新head的值为原来的残留网络
                head[k]=fhead[k];
                yong=fyong;//
                        addedge(fa,fb,inf);
                        addedge(fb,fa,0);
                        fma=dinic_maxflow(1);
                        if(fma>ma)//求出最大值
                            ma=fma;
                }
                printf("%d\n",ma+maxflow);
       }
return 0;
}