• POJ 2125 最小割


    题意:

    N个点M条边的有向图,给出如下两种操作。
    删除点i的所有出边,代价是Ai。
    删除点j的所有入边,代价是Bj。
    求最后删除图中所有的边的最小代价。

    其实就是二分图最小点权覆盖。

    定义:从x或者y集合中选取一些点,使这些点覆盖所有的边,并且选出来的点的权值尽可能小。

    题解:

    拆点。n个点拆成2n个点(左右各n个,i与(i+n)对应,之间连容量INF的边),S和i连容量为Ai的边,(i+n)与T之间连容量为Bi的边,求最小割即可

    这样做为什么对呢?

    当一条边存在的条件就是网络中还存在从S到T的非满流边!

    方案输出不多说。。

    View Code
     1 #include <cstdio>
     2 #include <cstring>
     3 #include <cstdlib>
     4 #include <iostream>
     5 
     6 #define N 300
     7 #define M 20000
     8 #define INF 99999999
     9 
    10 using namespace std;
    11 
    12 int to[M],next[M],head[N],len[M],cnt,layer[N],n,m,S,T,q[M];
    13 bool vis[N];
    14 
    15 inline void add(int u,int v,int w)
    16 {
    17     to[cnt]=v; len[cnt]=w; next[cnt]=head[u]; head[u]=cnt++;
    18     to[cnt]=u; len[cnt]=0; next[cnt]=head[v]; head[v]=cnt++;
    19 }
    20 
    21 void read()
    22 {
    23     memset(head,-1,sizeof head);cnt=0;
    24     scanf("%d%d",&n,&m);
    25     S=0,T=n+n+1;
    26     for(int i=1,a;i<=n;i++) scanf("%d",&a),add(i+n,T,a);
    27     for(int i=1,a;i<=n;i++) scanf("%d",&a),add(S,i,a);
    28     for(int i=1,a,b;i<=m;i++) scanf("%d%d",&a,&b),add(a,b+n,INF);
    29 }
    30 
    31 bool bfs()
    32 {
    33     memset(layer,-1,sizeof layer);
    34     int h=1,t=2,sta;
    35     q[1]=S; layer[S]=0;
    36     while(h<t)
    37     {
    38         sta=q[h++];
    39         for(int i=head[sta];~i;i=next[i])
    40             if(len[i]>0&&layer[to[i]]<0)
    41             {
    42                 layer[to[i]]=layer[sta]+1;
    43                 q[t++]=to[i];
    44             }
    45     }
    46     return layer[T]!=-1;
    47 }
    48 
    49 int find(int u,int cur_flow)
    50 {
    51     if(u==T) return cur_flow;
    52     int result=0,tmp;
    53     for(int i=head[u];~i;i=next[i])
    54         if(len[i]>0&&layer[to[i]]==layer[u]+1)
    55         {
    56             tmp=find(to[i],min(cur_flow-result,len[i]));
    57             len[i]-=tmp; len[i^1]+=tmp; result+=tmp;
    58         }
    59     if(!result) layer[u]=-1;
    60     return result;
    61 }
    62 
    63 void dfs(int u)
    64 {
    65     vis[u]=true;
    66     for(int i=head[u];~i;i=next[i])
    67         if(!vis[to[i]]&&len[i])
    68             dfs(to[i]);
    69 }
    70 
    71 void dinic()
    72 {
    73     int ans=0;
    74     while(bfs()) ans+=find(S,INF);
    75     printf("%d\n",ans);
    76     dfs(S);
    77     ans=0;
    78     for(int i=1;i<=n;i++)  
    79         ans+=(!vis[i])+(vis[i+n]);  
    80        printf("%d\n",ans);
    81     for(int i=1;i<=n;i++)  
    82     {  
    83         if(!vis[i]) printf("%d -\n",i);
    84         if(vis[i+n]) printf("%d +\n",i);
    85     }
    86 }
    87 
    88 int main()
    89 {
    90     read();
    91     dinic();
    92     return 0;
    93 }
    没有人能阻止我前进的步伐,除了我自己!
  • 相关阅读:
    浅析Java CompletionService
    经验总结13--EF配置
    消息摘要算法-HMAC算法
    03012_预处理对象executeQuery方法(实现数据库的查询)
    GO学习笔记:函数defer
    GO学习笔记:函数传值与传指针
    GO学习笔记:函数作为值、类型
    GO学习笔记:函数Panic和Recover
    GO学习笔记:import
    GO学习笔记:struct类型
  • 原文地址:https://www.cnblogs.com/proverbs/p/2851932.html
Copyright © 2020-2023  润新知