dinic

    xiaoxiao2025-08-10  9

    #include<stdio.h>   #include<string.h>   #define MAXN 20   #define MAXE 40   #define typec int   const typec inf = 0x3f3f3f3f;   struct edge{int x,y,nxt; typec c;}bf[MAXE];//bf用来查找某节点相连的所有节点   int ne,head[MAXN],ps[MAXN],dep[MAXN];   void addedge(int x,int y,typec c)   {       bf[ne].x=x;bf[ne].y=y;bf[ne].c=c;       bf[ne].nxt=head[x];head[x]=ne++;       bf[ne].x=y;bf[ne].y=x;bf[ne].c=0;       bf[ne].nxt=head[y];head[y]=ne++;   }   typec flow(int n,int s,int t)   {       typec tr,res=0;       int i,j,k,l,r,top;       while(1){           memset(dep,-1,n*sizeof(int));           for(l=dep[ps[0]=s]=0,r=1;l!=r;)//该部分为分层,dep[i]表示节点i在第几层,                                           //而用到ps[l,r]在 这里做广搜 的队列l表示队列左边 ,r表示队列的右边;           {               for(i=ps[l++],j=head[i];j!=-1;j=bf[j].nxt)//i为从队列头取一个元素赋值给i               {                   if(bf[j].c&&-1==dep[k=bf[j].y]){//当找到一个点相邻点,却流量不为0,同时还没有被分层!                       dep[k]=dep[i]+1;ps[r++]=k;                       if(k==t)//当发现汇点已经被分层,则结束分层,                       {                           l=r;                           break;                       }                   }               }           }           if(dep[t]==-1)break;//当发现不能分层,说明已经找不到汇点,最大网络流结束!             for(i=s,top=0;;)           {               if(i==t)//当一层层的深搜,找到了t,则需找出s到t路径中的最小容量tr,正向边减去该tr,反向边加上tr               {                   for(k=0,tr=inf;k<top;++k)//路径边的编号保存在 ps[top]里,                       if(bf[ps[k]].c<tr)tr=bf[ps[l=k]].c; //打雷获得最小tr,注意这里的 l=k,l将记录路径ps【l】                                                           //可以起到找到里s最近的那个正向边减去tr为0的点bf[ps[l]].x,方便后面回溯!(使增广路径后退至p中从源点可到达的最后一个顶点。)                       for(k=0;k<top;++k)//正向边减tr,反向变加tr                           bf[ps[k]].c-=tr,bf[ps[k]^1].c+=tr;                       res+=tr;i=bf[ps[top=l]].x;//最大流res+tr,并将回溯到的目标点,赋值 给当前点i               }               for(j=head[i];j!=-1;j=bf[j].nxt)//从当前点i找一个可以到达的点bf[j].y                   if(bf[j].c&&dep[i]+1==dep[bf[j].y])break;               if(j!=-1)//当找到一个可以到达的点,则可以跳到下一层,把当前点i改变为下一层的点bf[j].y,并将j放到为路径ps堆栈里               {                   ps[top++]=j;//将j放到为路径ps堆栈里                   i=bf[j].y;//当前点i改变为下一层的点bf[j].y               }               else//当当前 i点,不能跳转到下一层,则需要回溯               {                   if(!top)break;//当路径堆栈top==0时,说明i==s点,无法回溯!                   dep[i]=-1;i=bf[ps[--top]].x;//否则存在可回溯点,因为当前点i在该种分层法则不行的,                                          //可将dep[i]除掉(dep[i]=-1),再将回溯的bf[ps[--top]].x点复制给i!               }           }       }       return res;   }   int main()   {       int T,cas,e,s,t,n,maxflow,i;       int x,y,c;       double ans;       scanf("%d",&T);       while(T--)       {           scanf("%d%d%d%d",&n,&e,&s,&t);           memset(head,-1,sizeof(head));           for(i=ne=0;i<e;i++)           {               scanf("%d%d%d",&x,&y,&c);               addedge(x,y,c);           }           int maxedge=0;           maxflow=flow(n,s,t);           ans=(double)maxflow/(double)maxedge;           printf("%0.3lf\n",ans);                  }       return 0;  

    }

    1:分层,2:找增广路,然后回溯。找不到了以后,返回1。直到无法分层

    转载请注明原文地址: https://ju.6miu.com/read-1301602.html
    最新回复(0)