zoukankan      html  css  js  c++  java
  • bzoj 1565 [NOI2009]植物大战僵尸

    拓扑排序+最小割。

    每个植物有它保护的一些植物,等价于选一些点的先决条件是其它一些点,最大权闭合子图问题。

    发现图里有环,所以环里的点都不能选,先决条件是环里的点的点也不能选,所以把所有边反向拓扑排序,拓扑不到的点不能选。

    无视掉不能选的点后裸最大权闭合子图建图就好了。

    一个最大权闭合子图裸题的题解

      1 #include<iostream>
      2 #include<cstring>
      3 #include<cstdio>
      4 #include<algorithm>
      5 #include<queue>
      6 using namespace std;
      7 const int dian=605;
      8 const int bian=1000005;
      9 const int INF=0x3f3f3f3f;
     10 int h[dian],nxt[bian],ver[bian],val[bian],ch[dian],cr[dian];
     11 int qz[dian],num[dian],dbh[dian][dian],in[dian],v[dian];
     12 int n,m,tot,aa,bb,cc,ans;
     13 int S,T;
     14 int bh(int a,int b){
     15     return (a-1)*m+b;
     16 }
     17 void add1(int a,int b){
     18     tot++;ver[tot]=b;nxt[tot]=h[a];h[a]=tot;in[b]++;
     19 }
     20 void toposort(){
     21     queue<int>q;
     22     for(int i=1;i<=n*m;i++)
     23         if(!in[i])
     24             q.push(i);
     25     while(!q.empty()){
     26         int x=q.front();
     27         q.pop();
     28         v[x]=1;
     29         for(int i=h[x];i;i=nxt[i]){
     30             int y=ver[i];
     31             in[y]--;
     32             if(!in[y])
     33                 q.push(y);
     34         }
     35     }
     36 }
     37 void add(int a,int b,int c){
     38     tot++;ver[tot]=b;val[tot]=c;nxt[tot]=h[a];h[a]=tot;
     39     tot++;ver[tot]=a;val[tot]=0;nxt[tot]=h[b];h[b]=tot;
     40 }
     41 bool tell(){
     42     memset(ch,-1,sizeof(ch));
     43     queue<int>q;
     44     q.push(S);
     45     ch[S]=0;
     46     while(!q.empty()){
     47         int t=q.front();
     48         q.pop();
     49         for(int i=h[t];i;i=nxt[i])
     50             if(ch[ver[i]]==-1&&val[i]){
     51                 ch[ver[i]]=ch[t]+1;
     52                 q.push(ver[i]);
     53             }
     54     }
     55     return ch[T]!=-1;
     56 }
     57 int zeng(int a,int b){
     58     if(a==T)
     59         return b;
     60     int r=0;
     61     for(int i=cr[a];i&&b>r;i=nxt[i])
     62         if(ch[ver[i]]==ch[a]+1&&val[i]){
     63             int t=zeng(ver[i],min(b-r,val[i]));
     64             val[i]-=t,r+=t,val[i^1]+=t;
     65             if(val[i])
     66                 cr[a]=i;
     67         }
     68     if(!r)
     69         ch[a]=-1;
     70     return r;
     71 }
     72 int dinic(){
     73     int r=0,t;
     74     while(tell()){
     75         for(int i=1;i<=n*m+2;i++)
     76             cr[i]=h[i];
     77         while(t=zeng(S,INF))
     78             r+=t;
     79     }
     80     return r;
     81 }
     82 int main(){
     83     memset(h,0,sizeof(h));
     84     memset(nxt,0,sizeof(nxt));
     85     memset(num,0,sizeof(num));
     86     memset(in,0,sizeof(in));
     87     memset(v,0,sizeof(v));
     88     tot=0,ans=0;
     89     scanf("%d%d",&n,&m);
     90     S=n*m+1,T=n*m+2;
     91     for(int i=1;i<=n;i++)
     92         for(int j=1;j<=m;j++){
     93             scanf("%d",&aa);
     94             qz[bh(i,j)]=aa;
     95             scanf("%d",&aa);
     96             for(int k=1;k<=aa;k++){
     97                 scanf("%d%d",&bb,&cc);
     98                 num[bh(i,j)]++;
     99                 dbh[bh(i,j)][num[bh(i,j)]]=bh(bb+1,cc+1);
    100                 add1(bh(i,j),bh(bb+1,cc+1));
    101             }
    102         }
    103     for(int i=1;i<=n;i++)
    104         for(int j=2;j<=m;j++)
    105             add1(bh(i,j),bh(i,j-1));
    106     toposort();
    107     memset(h,0,sizeof(h));
    108     memset(nxt,0,sizeof(nxt));
    109     tot=1;
    110     for(int i=1;i<=n;i++)
    111         for(int j=1;j<=m;j++)
    112             if(v[bh(i,j)]){
    113                 if(qz[bh(i,j)]>0){
    114                     ans+=qz[bh(i,j)];
    115                     add(S,bh(i,j),qz[bh(i,j)]);
    116                 }
    117                 else if(qz[bh(i,j)]<0)
    118                     add(bh(i,j),T,-qz[bh(i,j)]);
    119                 for(int k=1;k<=num[bh(i,j)];k++)
    120                     if(v[dbh[bh(i,j)][k]])
    121                         add(dbh[bh(i,j)][k],bh(i,j),INF);
    122             }
    123     for(int i=1;i<=n;i++)
    124         for(int j=1;j<m;j++)
    125             if(v[bh(i,j)]&&v[bh(i,j+1)])
    126                 add(bh(i,j),bh(i,j+1),INF);
    127     printf("%d",ans-dinic());
    128     return 0;
    129 }
  • 相关阅读:
    SQL之层次查询
    GROUP函数
    SQL之统计
    正则表达式
    聚合函数,分析函数
    oracle函数
    Vue3.0优化
    浅谈FC
    短链接生成原理
    Vue路由传参
  • 原文地址:https://www.cnblogs.com/dugudashen/p/6273095.html
Copyright © 2011-2022 走看看