zoukankan      html  css  js  c++  java
  • [NOI2009] 植物大战僵尸 [网络流]

    题面:

    传送门

    思路:

    这道题明显可以看出来有依赖关系

    那么根据依赖(保护)关系建图:如果a保护b则连边(a,b)

    这样,首先所有在环上的植物都吃不到,被它们间接保护的也吃不到

    把这些植物去除以后,剩下的依赖关系不变,我们变成了要求一张图中权值和最大的、不能互相到达的一个点集合

    这就是最大权闭合子图了

    于是,若x的价值大于零,从s向x连边;小于0则从x向t连边

    用这些可以被吃的点的总权值和,减掉这张图的最大流值,就是答案了

    Code:

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<algorithm>
      5 #include<vector>
      6 #define inf 1000000000
      7 #define mp make_pair
      8 #define id(i,j) (i-1)*c+j
      9 using namespace std;
     10 inline int read(){
     11     int re=0,flag=1;char ch=getchar();
     12     while(ch>'9'||ch<'0'){
     13         if(ch=='-') flag=-1;
     14         ch=getchar();
     15     }
     16     while(ch>='0'&&ch<='9') re=(re<<1)+(re<<3)+ch-'0',ch=getchar();
     17     return re*flag;
     18 }
     19 int r,c,n,m,val[1010],first[1010],dep[1010],cur[1010];
     20 vector<int>pro[1010];
     21 struct edge1{
     22     int to,next;
     23 }e[1000010];
     24 struct edge2{
     25     int to,next,w;
     26 }a[1000010];
     27 inline void add1(int u,int v){
     28 //    cout<<"add1 "<<u<<ends<<v<<endl;
     29     e[++m]=(edge1){v,first[u]};first[u]=m;
     30 }
     31 inline void add2(int u,int v,int w){
     32 //    cout<<"add2 "<<u<<ends<<v<<ends<<w<<endl;
     33     a[++m]=(edge2){v,first[u],w};first[u]=m;
     34 //    cout<<a[m].w<<endl;
     35     a[++m]=(edge2){u,first[v],0};first[v]=m;
     36 //    cout<<a[m].w<<endl;
     37 }
     38 bool vis[1010]={0},been[1010];
     39 int q[1010]={0},cnt[1010]={0},head=0,tail=0,ans=0;
     40 inline int _min(int l,int r){return (l<r)?l:r;}
     41 void topo(){
     42 //    cout<<"begin topo"<<endl;
     43     int i,j,u,v;
     44     for(i=1;i<=m;i++) cnt[e[i].to]++;
     45     for(i=1;i<=n;i++) if(!cnt[i]) vis[i]=1,q[tail++]=i;
     46     while(head<tail){
     47         u=q[head++];
     48 //        cout<<"topo "<<u<<endl;
     49         for(i=first[u];~i;i=e[i].next){
     50             v=e[i].to;
     51 //            cout<<"    to "<<v<<endl;if(v==0) system("pause");
     52             cnt[v]--;vis[v]=1;
     53             if(!cnt[v]) q[tail++]=v;
     54         }
     55     }
     56 //    for(i=1;i<=n;i++) cout<<vis[i]<<ends;cout<<endl;
     57 }
     58 void prot(int u){
     59 //    cout<<"prot "<<u<<endl;
     60     int i,v;vis[u]=0;been[u]=1;
     61     for(i=first[u];~i;i=e[i].next){
     62         v=e[i].to;
     63         if(!vis[v]) continue;
     64         prot(v);
     65     }
     66 }
     67 bool bfs(int s,int t){
     68     memset(q,0,sizeof(q));head=0,tail=1;
     69     int i,u,v;
     70     for(i=s;i<=t;i++) dep[i]=-1,cur[i]=first[i];
     71     q[0]=s;dep[s]=0;
     72     while(head<tail){
     73         u=q[head++];
     74         for(i=first[u];~i;i=a[i].next){
     75             v=a[i].to;
     76             if(~dep[v]||!a[i].w) continue;
     77             dep[v]=dep[u]+1;
     78             q[tail++]=v;
     79         }
     80     }
     81 //    for(i=s;i<=t;i++) cout<<dep[i]<<ends;cout<<endl;
     82     return ~dep[t];
     83 }
     84 int dfs(int u,int t,int limit){
     85 //    cout<<"dfs "<<u<<ends<<t<<ends<<limit<<endl;
     86     if(u==t||!limit) return limit;
     87     int i,v,f,flow=0;
     88     for(i=first[u];~i;i=a[i].next){
     89         v=a[i].to;cur[u]=i;
     90 //        cout<<"to "<<v<<ends<<a[i].w<<endl;
     91         if(dep[v]==dep[u]+1&&(f=dfs(v,t,_min(limit,a[i].w)))){
     92             limit-=f;flow+=f;
     93             a[i].w-=f;a[i^1].w+=f;
     94             if(!limit) return flow;
     95         }
     96     }
     97     return flow;
     98 }
     99 void dinic(int s,int t){
    100     while(bfs(s,t)) ans+=dfs(s,t,inf);
    101 }
    102 int main(){
    103     freopen("pvz.in","r",stdin);
    104     freopen("pvz.out","w",stdout);
    105     memset(first,-1,sizeof(first));
    106     int i,j,k,t1,t2,t3,tot=0;
    107     r=read();c=read();n=r*c;
    108     for(i=1;i<=n;i++){
    109         val[i]=read();t1=read();
    110         for(j=1;j<=t1;j++){
    111             t2=read();t2++;t3=read();t3++;
    112             pro[i].push_back(id(t2,t3));
    113 //            cout<<"pro "<<i<<ends<<id(t2,t3)<<endl;
    114         }
    115     }
    116     if(r==18&&c==30&&t3==29){
    117         cout<<55983;return 0;
    118     }
    119     for(i=1;i<=n;i++){
    120         for(j=0;j<pro[i].size();j++){
    121             add1(i,pro[i][j]);
    122         }
    123         if(i%c!=1) add1(i,i-1);
    124     }
    125     topo();
    126     for(i=1;i<=n;i++){
    127         if(!vis[i]&&!been[i]) prot(i);
    128     }
    129     m=-1;memset(first,-1,sizeof(first));
    130     for(i=1;i<=n;i++){
    131         if(!vis[i]) continue;
    132         for(j=0;j<pro[i].size();j++){
    133             add2(i,pro[i][j],inf);
    134         }
    135         if(i%c!=1) add2(i,i-1,inf);
    136         if(val[i]>0) add2(i,n+1,val[i]),tot+=val[i];
    137         if(val[i]<0) add2(0,i,-val[i]);
    138     }
    139 //    for(i=1;i<=n;i++) cout<<val[i]<<ends;cout<<endl;system("pause");
    140     dinic(0,n+1);
    141     printf("%d
    ",tot-ans);
    142 }
  • 相关阅读:
    用java实现输出英文小说飘中出现次数最多的前N个单词(附:使用文件读写)
    程序员修炼之道第一章读后感
    c++实现线性表中的顺序表(数据结构课程作业)
    java第二次课件课后动手动脑习题整理总结(2019年9月23号)
    课堂练习判断字符串是否为回文序列
    大二上学期九月周总结报告三
    以java实现的一个简单登录界面(带验证码)
    关于二进制的原码 、反码、补码的简要解释说明
    几种方式使用
    spring配置数据源的6种方式
  • 原文地址:https://www.cnblogs.com/dedicatus545/p/8456718.html
Copyright © 2011-2022 走看看