zoukankan      html  css  js  c++  java
  • 太空飞行计划 网络流

    经典的最大权闭合子图问题;

    这种问题的求解思路是:

    建图:将s连边向权值为正的点,通过依赖关系连接权值为正的点和权值为负的点,权值为负的点连边向t;

    求c=最小割,a=所有权值为正的节点权值和,ans=a-c;

    证明过程网上是有的;

    用dinic敲的,但是用的还不熟练;

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<string>
     5 #include<cstdlib>
     6 #include<ctime>
     7 #include<algorithm>
     8 using namespace std;
     9 const int maxn=200;
    10 const int inf=1000000000;
    11 const int s=0,t=120;
    12 struct node{
    13     int y,next,flow,re;
    14 }e[maxn*10];
    15 int linkk[maxn],len=0,n,m,g[maxn][maxn],cnt[maxn],w[maxn],sum=0;
    16 void print(int x){printf("%d
    ",x);}
    17 void print(int x,int y){printf("%d %d
    ",x,y);}
    18 void insert(int x,int y,int flow){
    19     e[++len].y=y;e[len].flow=flow;
    20     e[len].next=linkk[x];linkk[x]=len;e[len].re=len+1;
    21     e[++len].y=x;e[len].flow=0;
    22     e[len].next=linkk[y];linkk[y]=len;e[len].re=len-1;
    23 }
    24 bool flag=0;
    25 int read(){
    26     int x=0;char ch=getchar();
    27     while(ch<'0'||ch>'9')ch=getchar();
    28     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    29     if(ch=='
    ')flag=1;
    30     return x;
    31 }
    32 void init(){
    33     scanf("%d%d",&n,&m);
    34     int v;
    35     for(int i=1;i<=n;i++){
    36         scanf("%d",&v);insert(s,i,v);
    37         flag=0;sum+=v;
    38         while(!flag){cnt[i]++;g[i][cnt[i]]=read();}
    39     }
    40     for(int i=1;i<=m;i++)scanf("%d",&w[i]);
    41     for(int i=1;i<=n;i++)
    42         for(int j=1;j<=cnt[i];j++)
    43             insert(i,g[i][j]+n,inf);
    44     for(int i=1;i<=m;i++)insert(i+n,t,w[i]);
    45 }
    46 int q[maxn],tail=0,level[maxn],head=0;
    47 bool bfs(){
    48     memset(level,-1,sizeof(level));
    49     head=0;tail=0;level[s]=1;q[++tail]=s;
    50     while(++head<=tail){
    51         int x=q[head];
    52         for(int i=linkk[x];i;i=e[i].next){
    53             if(level[e[i].y]==-1&&e[i].flow){
    54                 q[++tail]=e[i].y;
    55                 level[e[i].y]=level[x]+1;
    56             }
    57         }
    58     }
    59     return level[t]>0;
    60 }
    61 int find(int x,int flow){
    62     if(x==t)return flow;
    63     int maxflow=0,d=0;
    64     for(int i=linkk[x];i&&maxflow<flow;i=e[i].next){
    65         if(level[e[i].y]==level[x]+1&&e[i].flow){
    66             if(d=find(e[i].y,min(flow-maxflow,e[i].flow))){
    67                 maxflow+=d;
    68                 e[i].flow-=d;
    69                 e[e[i].re].flow+=d;
    70             }
    71         }
    72     }
    73     if(!maxflow)level[x]=-1;
    74     return maxflow;
    75 }
    76 void work(){
    77     int d=0,ans=0;
    78     while(bfs())
    79         while(d=find(s,inf))
    80             ans+=d;
    81     cout<<sum-ans<<endl;
    82 }
    83 int main(){
    84     //freopen("1.in","r",stdin);
    85     //freopen("1.out","w",stdout);
    86     init();
    87     work();
    88 }
    View Code
  • 相关阅读:
    POJ 2018 二分
    873. Length of Longest Fibonacci Subsequence
    847. Shortest Path Visiting All Nodes
    838. Push Dominoes
    813. Largest Sum of Averages
    801. Minimum Swaps To Make Sequences Increasing
    790. Domino and Tromino Tiling
    764. Largest Plus Sign
    Weekly Contest 128
    746. Min Cost Climbing Stairs
  • 原文地址:https://www.cnblogs.com/chadinblog/p/5861607.html
Copyright © 2011-2022 走看看