b2OJ_1565_[NOI2009]植物大战僵尸_拓扑排序+最大权闭合子
题意:n*m个植物,每个植物有分数(可正可负),和能保护植物的位置。只能从右往左吃,并且不能吃正被保护着的,可以一个不吃,求获得的最大分数。
分析:把每个植物向能保护它的植物连边。源点连正权点,负权点连汇点。
考虑在一个环上的植物是吃不到的,我们可以用拓扑排序确定哪些是能吃的。
然后求一遍最大权闭合子图就是答案。
代码:
1 #include <stdio.h> 2 #include <string.h> 3 #include <algorithm> 4 #include <queue> 5 using namespace std; 6 #define S (n*m+1) 7 #define T (n*m+2) 8 #define P(x,y) (m*(x-1)+y) 9 #define inf 100000000 10 int head[700],to[1000010],nxt[1000010],flow[1000010],c[1000010],cnt=1,dep[700]; 11 int n,m,can[700],sum,val[700]; 12 void add(int u,int v,int f) 13 { 14 to[++cnt]=v;nxt[cnt]=head[u];head[u]=cnt;flow[cnt]=f; 15 to[++cnt]=u;nxt[cnt]=head[v];head[v]=cnt;flow[cnt]=0; 16 } 17 bool bfs() 18 { 19 queue <int> q; 20 memset(dep,0,sizeof(dep)); 21 q.push(S);dep[S]=1; 22 while(q.size()) 23 { 24 int x=q.front();q.pop(); 25 for(int i=head[x];i;i=nxt[i]) 26 { 27 if(!dep[to[i]]&&flow[i]&&can[to[i]]) 28 { 29 dep[to[i]]=dep[x]+1; 30 q.push(to[i]); 31 } 32 } 33 } 34 return dep[T]; 35 } 36 int dfs(int x,int mf) 37 { 38 if(x==T)return mf; 39 int nf=0; 40 for(int i=head[x];i;i=nxt[i]) 41 { 42 if(dep[to[i]]==dep[x]+1&&flow[i]&&can[to[i]]) 43 { 44 int tmp=dfs(to[i],min(flow[i],mf-nf)); 45 nf+=tmp; 46 flow[i]-=tmp; 47 flow[i^1]+=tmp; 48 if(nf==mf)break; 49 } 50 } 51 dep[x]=0; 52 return nf; 53 } 54 void dinic() 55 { 56 int ans=0,f; 57 while(bfs()) 58 { 59 while(f=dfs(S,inf)) 60 { 61 ans+=f; 62 } 63 } 64 printf("%d",sum-ans); 65 } 66 void topsort() 67 { 68 queue <int> q; 69 for(int i=1;i<=T;i++) 70 { 71 if(!c[i])q.push(i); 72 } 73 while(q.size()) 74 { 75 int x=q.front();q.pop(); 76 can[x]=1; 77 if(val[x]>0)sum+=val[x]; 78 for(int i=head[x];i;i=nxt[i]) 79 { 80 c[to[i]]--; 81 if(c[to[i]]==0)q.push(to[i]); 82 } 83 } 84 } 85 int main() 86 { 87 scanf("%d%d",&n,&m); 88 int x,y,z,w; 89 for(int i=1;i<=n*m;i++) 90 { 91 scanf("%d%d",&x,&y); 92 val[i]=x; 93 if(x>0)add(S,i,x),c[S]++; 94 else add(i,T,-x),c[i]++; 95 if(i%m)add(i,i+1,inf),c[i]++; 96 while(y--) 97 { 98 scanf("%d%d",&z,&w); 99 add(P(z+1,w+1),i,inf); 100 c[P(z+1,w+1)]++; 101 } 102 } 103 topsort(); 104 dinic(); 105 } 106 107 /*************************************************************** 108 Problem: 1580 109 User: 20170105 110 Language: C++ 111 Result: Accepted 112 Time:320 ms 113 Memory:16704 kb 114 ****************************************************************/
原文地址:https://www.cnblogs.com/suika/p/8424481.html
时间: 2024-10-10 12:48:20