题目大意:给定一个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;
}