zoukankan      html  css  js  c++  java
  • ZOJ 2532 网络流最小割

    求最小割的问题。

    题意:已知网络中有n个源点,m的中转站(也就是节点),一个汇点(编号为0)。给出网络,求一些边(增大这个边就可以增大汇点流量的边)。

    思路:一开始代码只找了有流=0就加入输出数组的情况,然而忽略了流向一条S->T的流有多个边权=0的情况,此时只增大一条边的值是没用的。

    所以除了用一次最大流算法后,还需要用两次dfs分别从超级源点S和汇点T开始搜索,这样就可以把有多个0-0-0和单个边权为0的情况判断出来。

      1 #include <cstdio>
      2 #include <cstring>
      3 #include <cstdlib>
      4 #include <cmath>
      5 #include <queue>
      6 #include <stack>
      7 #include <map>
      8 #include <set>
      9 #include <vector>
     10 #include <algorithm>
     11 using namespace std;
     12 const int INF = 0x3f3f3f3f;
     13 typedef struct node
     14 {
     15     int u;
     16     int v;
     17     int Flow;
     18     int next;
     19 }Line;
     20 Line Li[2200];
     21 int Head[110],top;
     22 int vis[110],ans[110];
     23 bool vis1[110],vis2[110];
     24 int n,m,l;
     25 int s,t;
     26 void AddEdge(int u,int v,int f)
     27 {
     28     Li[top].v=v; Li[top].u=u;
     29     Li[top].Flow=f;
     30     Li[top].next=Head[u];
     31     Head[u]=top++;
     32 }
     33 bool BFS()
     34 {
     35     memset(vis,-1,sizeof(vis));
     36     vis[s]=0;
     37     queue<int >Q;
     38     Q.push(s);
     39     while(!Q.empty())
     40     {
     41         int u=Q.front();
     42         Q.pop();
     43         for(int i=Head[u];i!=-1;i=Li[i].next)
     44         {
     45             if(Li[i].Flow&&vis[Li[i].v]==-1)
     46             {
     47                 vis[Li[i].v]=vis[u]+1;
     48                 Q.push(Li[i].v);
     49             }
     50         }
     51     }
     52     return vis[t]!=-1;
     53 }
     54 int DFS(int u,int f)
     55 {
     56     if(u==t)
     57     {
     58         return f;
     59     }
     60     int ans=0;
     61     for(int i=Head[u];i!=-1;i=Li[i].next)
     62     {
     63         if(Li[i].Flow&&vis[Li[i].v]==vis[u]+1)
     64         {
     65             int d=DFS(Li[i].v,min(f,Li[i].Flow));
     66             f-=d;
     67             Li[i].Flow-=d;
     68             Li[i^1].Flow+=d;
     69             ans+=d;
     70         }
     71     }
     72     return ans;
     73 }
     74 void dfs(int u,bool *vist,int op)
     75 {
     76     vist[u]=true;
     77     for(int i=Head[u];i!=-1;i=Li[i].next)
     78     {
     79         if(!vist[Li[i].v]&&Li[i^op].Flow!=0)
     80         {
     81             dfs(Li[i].v,vist,op);
     82         }
     83     }
     84 }
     85 void Dinic()//网络流进行增广
     86 {
     87     int ans;
     88     while(BFS())
     89     {
     90         ans=DFS(s,INF);
     91         printf("!
    ");
     92     }
     93 }
     94 int main()
     95 {
     96     while(~scanf("%d %d %d",&n,&m,&l))
     97     {
     98         if(n+m+l==0)
     99         {
    100             break;
    101         }
    102         s=n+m+1;//源点
    103         t=0;//汇点
    104         memset(Head,-1,sizeof(Head));
    105         int a,b,c;
    106         top = 0;
    107         for(int i=0;i<l;i++)
    108         {
    109             scanf("%d %d %d",&a,&b,&c);
    110             AddEdge(a,b,c);//建立边,正向为c,负向为0
    111             AddEdge(b,a,0);
    112         }
    113         for(int i=1;i<=n;i++)
    114         {
    115             AddEdge(s,i,INF);
    116             AddEdge(i,s,0);//建立城市与源点之间的边,权值为INF
    117         }
    118         Dinic();
    119         memset(vis1,false,sizeof(vis1));
    120         memset(vis2,false,sizeof(vis2));
    121         dfs(s,vis1,0);//从源点向汇点搜索,标记还有剩余流的点
    122         dfs(t,vis2,1);//从汇点到源点搜索,标记还有剩余流的点
    123         int num=0;
    124         for(int i=0;i<l;i++)
    125         {
    126             if(Li[i<<1].Flow==0&&vis1[Li[i<<1].u]&&vis2[Li[i<<1].v])
    127                 ans[num++]=i+1;//如果一条边的u与v都被标记,表明s->u,v->t,但是这条边是满流,所以提升这条边。
    128         }
    129         if(num)
    130         {
    131             for(int i=0;i<num;i++)
    132             {
    133                 if(i)printf(" ");
    134                 printf("%d",ans[i]);
    135             }
    136         }
    137         printf("
    ");
    138     }
    139     return 0;
    140 }
    View Code

    代码转自(https://blog.csdn.net/huayunhualuo/article/details/50554800)这个题解的板子跟我的差不多就转了

    适当比较,砥砺前行
  • 相关阅读:
    Linux目录
    find命令
    107. Binary Tree Level Order Traversal II
    grep命令
    110. Balanced Binary Tree
    111. Minimum Depth of Binary Tree
    什么是泛型
    自动装箱与拆箱
    HDU 3001 Travelling (状压DP + BFS)
    POJ 3411 Paid Roads (状态压缩+BFS)
  • 原文地址:https://www.cnblogs.com/llllrj/p/9391062.html
Copyright © 2011-2022 走看看