• POJ 3204 最小割


    题意:

    在一个网络里面,问增大哪条边的容量可以使整个网络的流量增大,输出这种边个数。

    题解:

    显然这些边是最小割边集的子集。

    对于边u-->v,当且仅当能从S沿着非满流的正向边遍历到u,从T沿着非满流的正向边遍历到v时,边u-->v是满足题意的边

    两遍dfs求解~

    View Code
     1 #include <iostream>
     2 #include <cstring>
     3 #include <cstdio>
     4 #include <cstdlib>
     5 #include <algorithm>
     6 
     7 #define N 1000
     8 #define M 500010
     9 #define INF 1e9
    10 
    11 using namespace std;
    12 
    13 int head[N],next[M],to[M],len[M];
    14 int layer[N],q[M*10],vis[N];
    15 int n,m,cnt,S,T;
    16 
    17 inline void add(int u,int v,int w)
    18 {
    19     to[cnt]=v; len[cnt]=w; next[cnt]=head[u]; head[u]=cnt++;
    20     to[cnt]=u; len[cnt]=0; next[cnt]=head[v]; head[v]=cnt++;
    21 }
    22 
    23 inline void read()
    24 {
    25     memset(head,-1,sizeof head); cnt=0;
    26     scanf("%d%d",&n,&m);
    27     S=1; T=n;
    28     for(int i=1,a,b,c;i<=m;i++)
    29     {
    30         scanf("%d%d%d",&a,&b,&c); a++; b++;
    31         add(a,b,c);
    32     }
    33 }
    34 
    35 inline bool bfs()
    36 {
    37     memset(layer,-1,sizeof layer);
    38     int h=1,t=2,sta;
    39     q[1]=S; layer[S]=0;
    40     while(h<t)
    41     {
    42         sta=q[h++];
    43         for(int i=head[sta];~i;i=next[i])
    44             if(len[i]&&layer[to[i]]<0)
    45             {
    46                 layer[to[i]]=layer[sta]+1;
    47                 q[t++]=to[i];
    48             }
    49     }
    50     return layer[T]!=-1;
    51 }
    52 
    53 inline int find(int u,int cur_flow)
    54 {
    55     if(u==T) return cur_flow;
    56     int res=0,tmp;
    57     for(int i=head[u];~i&&res<cur_flow;i=next[i])
    58         if(len[i]&&layer[to[i]]==layer[u]+1)
    59         {
    60             tmp=find(to[i],min(cur_flow-res,len[i]));
    61             len[i]-=tmp; len[i^1]+=tmp; res+=tmp;
    62         }
    63     if(!res) layer[u]=-1;
    64     return res;
    65 }
    66 
    67 inline void dfs1(int u)
    68 {
    69     vis[u]=1;
    70     for(int i=head[u];~i;i=next[i])
    71         if(vis[to[i]]==0&&len[i]>0) dfs1(to[i]);
    72 }
    73 
    74 inline void dfs2(int u)
    75 {
    76     vis[u]=2;
    77     for(int i=head[u];~i;i=next[i])
    78         if(vis[to[i]]==0&&len[i^1]>0) dfs2(to[i]);
    79 }
    80 
    81 inline void go()
    82 {
    83     int ans=0;
    84     while(bfs()) ans+=find(S,INF);
    85     dfs1(S); dfs2(T);
    86     ans=0;
    87     for(int i=0;i<cnt;i+=2)
    88         if(vis[to[i]]==2&&vis[to[i^1]]==1) ans++;
    89     printf("%d\n",ans);
    90 }
    91 
    92 int main()
    93 {
    94     read();
    95     go();
    96     return 0;
    97 }
    没有人能阻止我前进的步伐,除了我自己!
  • 相关阅读:
    Linux脚本文件注释
    Linux三剑客之grep命令
    Linux获取本机IP
    Linux的cut命令详解
    Linux的wc命令详解
    Linux的uniq命令详解
    Linux的sort命令详解
    shell之a+b求和脚本的三种写法
    shell的文件比较运算符和字符串比较运算符
    shell中变量$系列的含义
  • 原文地址:https://www.cnblogs.com/proverbs/p/2851886.html
Copyright © 2020-2023  润新知