• 网络流之最小割


    最小割的相关知识请参见:网络流问题

    I.     hdu4289    Control

    题意:给出一个由n个点,m条边组成的无向图。给出两个点s,t。对于图中的每个点,去掉这个点都需要一定的花费。求至少多少花费才能使得s和t之间不连通。

    分析:题意即求最小割,将每个点拆点,点与对应点的边权为去掉该点的花费,原图中所有边的边权赋为无穷大,跑一遍最大流即可。(最大流即最小割)

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cmath>
      4 #include<cstring>
      5 
      6 using namespace std;
      7 const int MAXN = 2010;
      8 const int MAXM = 1200012;
      9 const int INF = 0x3f3f3f3f;
     10 struct Edge 
     11 {
     12     int to, next, cap, flow;
     13 }edge[MAXM];
     14 int tol;
     15 int head[MAXN];
     16 void init() 
     17 {
     18     tol = 2;
     19     memset(head, -1, sizeof(head));
     20 }
     21 void addedge(int u, int v, int w, int rw=0) 
     22 {
     23     edge[tol].to = v; edge[tol].cap = w; edge[tol].flow = 0;
     24     edge[tol].next = head[u]; head[u] = tol++;
     25     edge[tol].to = u; edge[tol].cap = rw; edge[tol].flow = 0;
     26     edge[tol].next = head[v]; head[v] = tol++;
     27 }
     28 int Q[MAXN];
     29 int dep[MAXN], cur[MAXN], sta[MAXN];
     30 bool bfs(int s, int t, int n) 
     31 {
     32     int front = 0, tail = 0;
     33     memset(dep, -1, sizeof(dep[0])*(n+1));
     34     dep[s] = 0;
     35     Q[tail++] = s;
     36     while(front < tail)
     37     {
     38         int u = Q[front++];
     39         for(int i = head[u]; i != -1; i = edge[i].next) 
     40         {
     41             int v = edge[i].to;
     42             if(edge[i].cap > edge[i].flow && dep[v] == -1)                 {
     43                 dep[v] = dep[u] + 1;
     44                 if(v == t) return true;
     45                 Q[tail++] = v;
     46             }
     47         }
     48     }
     49     return false;
     50 }
     51 int dinic(int s, int t, int n) {
     52     int maxflow = 0;
     53     while(bfs(s, t, n)) {
     54         for(int i = 0; i < n; i++) cur[i] = head[i];
     55         int u = s, tail = 0;
     56         while(cur[s] != -1)
     57         {
     58             if(u == t) 
     59             {
     60                 int tp = INF;
     61                 for(int i = tail-1; i >= 0; i--)
     62                     tp = min(tp, edge[sta[i]].cap-edge[sta[i]].flow);
     63                 maxflow+=tp;
     64                 for(int i = tail-1; i >= 0; i--) {
     65                     edge[sta[i]].flow+=tp;
     66                     edge[sta[i]^1].flow-=tp;
     67                     if(edge[sta[i]].cap-edge[sta[i]].flow==0)
     68                         tail = i;
     69                 }
     70                 u = edge[sta[tail]^1].to;
     71             }
     72             else 
     73                 if(cur[u] != -1 && edge[cur[u]].cap > edge[cur[u]].flow && dep[u] + 1 == dep[edge[cur[u]].to]) 
     74                 {
     75                     sta[tail++] = cur[u];
     76                     u = edge[cur[u]].to;
     77                 }
     78                 else 
     79                 {
     80                     while(u != s && cur[u] == -1)
     81                         u = edge[sta[--tail]^1].to;
     82                     cur[u] = edge[cur[u]].next;
     83                 }
     84         }
     85     }
     86     return maxflow;
     87 }
     88 int n,m,s,d;
     89 
     90 int main()
     91 {
     92     while(~scanf("%d%d",&n,&m))
     93     {
     94         init();
     95         scanf("%d%d",&s,&d);
     96         int c;
     97         for(int i=0;i<n;++i)
     98         {
     99             scanf("%d",&c);
    100             addedge(i,i+n,c);
    101         }
    102         for(int i=1;i<=m;++i)
    103         {
    104             int a,b;
    105             scanf("%d%d",&a,&b);
    106             addedge(a-1+n,b-1,INF);
    107             addedge(b-1+n,a-1,INF);
    108         }
    109         cout<<dinic(s-1,d-1+n,2*n)<<endl;
    110     }
    111     return 0;
    112 }
    View Code

     J.     UVA10480    Sabotage

    题意:旧政府有一个很庞大的网络系统,可以很方便的指挥他的城市,起义军为了减少伤亡所以决定破坏他们的网络,使他们的首都(1号城市)和最大的城市(2号城市)不能联

    系,不过破坏不同的网络所花费的代价是不同的,现在起义军想知道最少花费的代价是多少,输出需要破坏的线路。

    分析:与 I 题一样,也是求最小割,只要算出最大流即可。不过题目要求输出最小割的边,这也是可以用网络流解决的,方法:求完最大流后,在残留网络中从源点 s 开始 dfs ,将能

    到达的点标号( c - f >0 的边),最后遍历一遍边集,将起点被标记、终点未被标记的边输出。(注意这是无向图,边只用输出一遍,而在有向图中,条件应该改为起点标号、终点未标或起点未标、终点标号的边)。

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cmath>
      4 #include<cstring>
      5 #include<algorithm>
      6 
      7 using namespace std;
      8 const int MAXN = 200;
      9 const int MAXM = 5000;
     10 const int INF = 0x3f3f3f3f;
     11 struct Edge 
     12 {
     13     int from,to, next, cap, flow;
     14 }edge[MAXM];
     15 int tol;
     16 int head[MAXN];
     17 void init() 
     18 {
     19     tol = 2;
     20     memset(head, -1, sizeof(head));
     21 }
     22 int min(int a,int b)
     23 {
     24     return a>b?b:a;
     25 }
     26 void addedge(int u, int v, int w, int rw=0) 
     27 {
     28     edge[tol].from=u;
     29     edge[tol].to = v; edge[tol].cap = w; edge[tol].flow = 0;
     30     edge[tol].next = head[u]; head[u] = tol++;
     31 }
     32 int Q[MAXN];
     33 int dep[MAXN], cur[MAXN], sta[MAXN];
     34 bool bfs(int s, int t, int n) 
     35 {
     36     int front = 0, tail = 0;
     37     memset(dep, -1, sizeof(dep[0])*(n+1));
     38     dep[s] = 0;
     39     Q[tail++] = s;
     40     while(front < tail)
     41     {
     42         int u = Q[front++];
     43         for(int i = head[u]; i != -1; i = edge[i].next) 
     44         {
     45             int v = edge[i].to;
     46             if(edge[i].cap > edge[i].flow && dep[v] == -1)                         {
     47                 dep[v] = dep[u] + 1;
     48                 if(v == t) return true;
     49                 Q[tail++] = v;
     50             }
     51         }
     52     }
     53     return false;
     54 }
     55 int dinic(int s, int t, int n) {
     56     int maxflow = 0;
     57     while(bfs(s, t, n)) {
     58         for(int i = 0; i < n; i++) cur[i] = head[i];
     59         int u = s, tail = 0;
     60         while(cur[s] != -1)
     61         {
     62             if(u == t) 
     63             {
     64                 int tp = INF;
     65                 for(int i = tail-1; i >= 0; i--)
     66                     tp = min(tp, edge[sta[i]].cap-edge[sta[i]].flow);
     67                 maxflow+=tp;
     68                 for(int i = tail-1; i >= 0; i--) {
     69                     edge[sta[i]].flow+=tp;
     70                     edge[sta[i]^1].flow-=tp;
     71                     if(edge[sta[i]].cap-edge[sta[i]].flow==0)
     72                         tail = i;
     73                 }
     74                 u = edge[sta[tail]].from;
     75             }
     76             else 
     77                 if(cur[u] != -1 && edge[cur[u]].cap > edge[cur[u]].flow && dep[u] + 1 == dep[edge[cur[u]].to]) 
     78                 {
     79                     sta[tail++] = cur[u];
     80                     u = edge[cur[u]].to;
     81                 }
     82                 else 
     83                 {
     84                     while(u != s && cur[u] == -1)
     85                         u = edge[sta[--tail]].from;
     86                     cur[u] = edge[cur[u]].next;
     87                 }
     88         }
     89     }
     90     return maxflow;
     91 }
     92 int n,m;
     93 bool vis[MAXN];
     94 
     95 void dfs(int u)
     96 {
     97     vis[u]=true;
     98     for(int i=head[u];i!=-1;i=edge[i].next)
     99     {
    100         int v=edge[i].to;
    101         if(edge[i].cap>edge[i].flow&&(!vis[v]))
    102                 dfs(v);
    103     }
    104 }
    105 
    106 int main()
    107 {
    108     while(~scanf("%d%d",&n,&m)&&n&&m)
    109     {
    110         init();
    111         for(int i=1;i<=m;++i)
    112         {
    113             int u,v,c;
    114             scanf("%d%d%d",&u,&v,&c);
    115             addedge(u-1,v-1,c);
    116             addedge(v-1,u-1,c);
    117         }
    118         dinic(0,1,n);
    119         memset(vis,false,sizeof(vis));
    120         dfs(0);
    121         for(int i=2;i<tol;i=i+2)
    122         {
    123             int u=edge[i].from;
    124             int v=edge[i].to;
    125             if(vis[u]!=vis[v])
    126             {
    127                 cout<<u+1<<" "<<v+1<<endl;
    128             }
    129         }
    130         cout<<endl;
    131     }
    132     return 0;
    133 }
    View Code
  • 相关阅读:
    作业: 小型购物系统1---按顺序编写
    字典操作学习小结
    字符操作学习笔记小结
    列表,元组等学习笔记小结
    模块及其数据类型小结
    python3学习笔记----基础知识1
    压力山大
    下周一开始上班啦!
    凌晨12点,沉迷学习,无法自拔...
    web前端开发2018年12月找工作总结
  • 原文地址:https://www.cnblogs.com/yaoyueduzhen/p/5080048.html
Copyright © 2020-2023  润新知