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
  • 相关阅读:
    堆排序
    搭建Struts2开发环境
    直接插入排序的小改进——希尔排序
    一个名声不好的排序算法(二)——冒泡排序算法
    一种名声不好的排序算法——简单选择排序算法
    直接插入排序算法:ArrayList实现和数组实现
    反射技术初步
    JAVA如何实现深拷贝
    书籍推荐(暂定,待续)
    Q/Z
  • 原文地址:https://www.cnblogs.com/chadinblog/p/5861607.html
Copyright © 2011-2022 走看看