首页 > 代码库 > BZOJ 1565 NOI2009 植物大战僵尸 最大权闭合图+拓扑排序
BZOJ 1565 NOI2009 植物大战僵尸 最大权闭合图+拓扑排序
题目大意:给定一个m*n的草坪,每块草坪上的植物有两个属性:
1.啃掉这个植物,获得收益x(可正可负)
2.保护(r,c)点的植物不被啃掉
任何一个点的植物存活时,它左侧的所有植物都无法被攻击
求最大收益
首先这个保护和被保护的关系就是最大权闭合图的连边关系 然后直接跑就行
然后我们就会发现没过样例0.0
原因当图出现环时,根据题意,环上的所有点都不能取(想象一个无冷却的食人花前面放一个坚果)
所以这题还要去掉环
由于环上的点不能取,所以所有指向环上的点的点都不能取
这个条件看起来不太好做,我们反向处理
由于环上的点不能取,所以所有反向图中环上的点指向的点都不能取
于是拓扑排序就可以处理了 所有拓扑排序排不到的点全都删掉即可
比较囧的是我一开始写的Tarjan(这题不能写Tarjan),而且Tarjan还写挂了,两个错误一异或就AC了0.0 逗尿了
顺便吐槽一下测试数据只有两个点有环 欺骗我们感情0.0
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define M 610 #define INF 0x7fffffff using namespace std; struct abcd{ int to,f,next; }table[500500]; int head[M],tot=1; int m,n,s,t,ans; int q[65540],d[M],f[M],into[M]; unsigned short r,h; bool usable[M]; void add(int x,int y,int z) { table[++tot].to=y; table[tot].f=z; table[tot].next=head[x]; head[x]=tot; table[++tot].to=x; table[tot].f=0; table[tot].next=head[y]; head[y]=tot; into[x]++; } void Topology_Sort() { int i; for(i=s;i<=t;i++) if(!into[i]) q[++r]=i; while(r!=h) { int x=q[++h]; usable[x]=1; if(f[x]>0) ans+=f[x]; for(i=head[x];i;i=table[i].next) if(i&1) { into[table[i].to]--; if(!into[table[i].to]) q[++r]=table[i].to; } } } bool BFS() { int i; memset(d,0,sizeof d); r=h;q[++r]=s;d[s]=1; while(r!=h) { int x=q[++h]; for(i=head[x];i;i=table[i].next) if( table[i].f && !d[table[i].to] && usable[table[i].to] ) { d[table[i].to]=d[x]+1; q[++r]=table[i].to; if(table[i].to==t) return true; } } return false; } int Dinic(int x,int flow) { int i,temp=flow; if(x==t) return flow; for(i=head[x];i;i=table[i].next) if( table[i].f && d[table[i].to]==d[x]+1 && temp ) { int k=Dinic( table[i].to , min(temp,table[i].f) ); if(!k) d[table[i].to]=0; temp-=k; table[i].f-=k; table[i^1].f+=k; } return flow-temp; } int main() { //freopen("pvz.in","r",stdin); //freopen("pvz.out","w",stdout); int i,j,x,y,r,c; cin>>m>>n; s=0;t=m*n+1; for(i=1;i<=m*n;i++) { scanf("%d",&f[i]); if(f[i]>0) add(s,i,f[i]); else add(i,t,-f[i]); scanf("%d",&y); for(j=1;j<=y;j++) { scanf("%d%d",&r,&c); add(r*n+c+1,i,INF); } if(i%n) add(i,i+1,INF); } Topology_Sort(); while( BFS() ) ans-=Dinic(s,INF); cout<<ans<<endl; }
BZOJ 1565 NOI2009 植物大战僵尸 最大权闭合图+拓扑排序
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。