zoukankan      html  css  js  c++  java
  • poj2987 Firing[最小割]

    题目


    求选最少点个数的最大权闭合子图。(板子题)


    最小割入门题,什么都不想说,丢个别人题解地址就跑。

    附加几点个人理解:与s相通的S点集是闭合子图,剩下的与t相通的T点集是其他的。任意一个割都保证了有一个闭合子图是S集。

    然后是选最少点个数,考虑加入最大权时存在多个方案,选的点个数不同,既然各方案都是闭合的,那我全选也是闭合的,就会创出更多权值,与之前最大权矛盾,所以最大权一定点数唯一,选法唯一。那就直接从s点找残量网络,把他的点集都找一下,计下数即可。←这里有个原理,做最小割(最大流),而最大流算好后因为最小割必然满流,所以最小割对应的边残量为0,则dfs时就不遍历残量为0的边。←刚才又提到一个结论,一定存在一个最大流使得最小割在其中满流,这里口胡证明一下,防止以后我忘了:最大流做完后s所能到的所有点S集,以及另一T集之间,应当是有一些边满流的也就是残量为0的,不然就可继续增广,就不是最大流了,那这些边对应了一个割CUT[S,T],再由任意流小于等于任意割结论(打个比方,水流将流到割断的地方,而水流量小于等于容量,故得证)知,任意一个割大于等于这个最大流,即大于等于这个割,那这个割就是最小割,而她满流。证毕。

    UPD:我现在看发现当时好像证的有点问题。。所以请不要信以为真,有空回来补详细的一些证明,当时只是个网络流初心者。

    我还是太菜了啊。

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cstring>
     4 #include<queue>
     5 using namespace std;
     6 typedef long long ll;
     7 typedef pair<int,int> pii;
     8 template<typename T>inline char MIN(T&A,T B){return A>B?A=B,1:0;}
     9 template<typename T>inline char MAX(T&A,T B){return A<B?A=B,1:0;}
    10 template<typename T>inline T _min(T A,T B){return A<B?A:B;}
    11 template<typename T>inline T _max(T A,T B){return A>B?A:B;}
    12 template<typename T>inline void inc(T&A,T B){A+=B;}
    13 template<typename T>inline T read(T&x){
    14     x=0;int f=0;char c;while(!isdigit(c=getchar()))if(c=='-')f=1;
    15     while(isdigit(c))x=x*10+c-'0',c=getchar();return f?x=-x:x;
    16 }
    17 const int N=5000+7,M=80000+7;ll INF=1ll<<40;
    18 int Head[N],cur[N],Next[M<<1],v[M<<1],dis[N],vis[N],tot=1,n,cnt,m,s,t;ll w[M<<1];
    19 
    20 inline void Addedge(int x,int y,ll z){
    21     v[++tot]=y,Next[tot]=Head[x],Head[x]=tot,w[tot]=z;
    22     v[++tot]=x,Next[tot]=Head[y],Head[y]=tot,w[tot]=0;
    23 }
    24 #define y v[j]
    25 inline int bfs(){
    26     queue<int> q;memset(dis,0,sizeof dis),dis[s]=1,q.push(s);
    27     for(register int i=1;i<=n+2;++i)cur[i]=Head[i];
    28     while(!q.empty()){
    29         int x=q.front();q.pop();
    30         for(register int j=Head[x];j;j=Next[j])if(w[j]&&!dis[y]){
    31             dis[y]=dis[x]+1,q.push(y);
    32             if(y==t)return 1;
    33         }
    34     }
    35     return 0;
    36 }
    37 ll dinic(int x,ll flow){
    38     if(!flow||x==t)return flow;
    39     ll rest=flow,k;
    40     for(register int j=cur[x];j&&rest;cur[x]=j,j=Next[j])if(w[j]&&dis[y]==dis[x]+1){
    41         if(!(k=dinic(y,_min(rest,w[j]))))dis[y]=0;
    42         rest-=k,w[j]-=k,w[j^1]+=k;
    43     }
    44     return flow-rest;
    45 }
    46 void dfs(int x){
    47     for(register int j=Head[x];j;j=Next[j])if(w[j]&&!vis[y])vis[y]=1,++cnt,dfs(y);
    48 }
    49 #undef y
    50 int x,y;
    51 ll maxflow,ans,z;
    52 
    53 int main(){//freopen("tmp.in","r",stdin);freopen("tmp.out","w",stdout);
    54     read(n),read(m);s=n+1,t=s+1;
    55     for(register int i=1;i<=n;++i)read(z)>0?(inc(ans,z),Addedge(s,i,z)):Addedge(i,t,-z);
    56     for(register int i=1;i<=m;++i)read(x),read(y),Addedge(x,y,INF);
    57     while(bfs())inc(maxflow,dinic(s,INF));
    58     ans-=maxflow;cnt=1,vis[s]=1,dfs(s);
    59     printf("%d %lld
    ",--cnt,ans);
    60     return 0;
    61 }

     Upd:今天被巨佬嘲讽了说我快读用位运算太慢。orzorzorzTQL

  • 相关阅读:
    数据结构(九)词典
    数据结构(八)高级搜索树
    电脑购买参数配置
    git命令
    Linux安装初始化
    电影TS、TC、BD版和HD版
    eclipse 自动生成json格式的toString()方法
    富文本编辑器-UEditor
    lucene教程--全文检索技术
    FileOperator 文件(夹)操作类
  • 原文地址:https://www.cnblogs.com/saigyouji-yuyuko/p/10360486.html
Copyright © 2011-2022 走看看