BZOJ1565
题目有点长qwq,读了很久才看懂。
这似乎是一道最大权闭合图的裸题,但是我们发现存在植物互相保护这种情况,即建出来的图不一定是DAG。那么我们可以拓扑排序找环,然后把环忽略。然后把不可攻击的点(即环上的点)不与虚拟源点和虚拟汇点连边,那么就不会影响答案了。
这题也更加加深了对该建模方式的理解,即如果需要获得正权的收益,且该点通过奇妙重重的方式连接到对面(负权点),那么一定要在汇点割去负权的损失才能获得正权的收益。
所以答案=正权和-最小割
(没想到瞎写一通还能1A
(逃
#include<bits/stdc++.h>
#define maxn 610
#define inf 0x3f3f3f3f
using namespace std;
struct node{
int to,f,m;
node*next,*rev;
}*con[maxn];
void addedge(int x,int y,int m)
{
node*p=new node;
p->to=y;
p->f=0;p->m=m;
p->next=con[x];
con[x]=p;
p=new node;
p->to=x;
p->f=p->m=0;
p->next=con[y];
con[y]=p;
con[x]->rev=con[y];
con[y]->rev=con[x];
}
int n,m,s,t,pts[maxn],de[maxn],dep[maxn];
int poi(int x,int y) {return x*m+y+1;}
bool can[maxn];
int dl[maxn],head=1,tail=0,ans;
void toposort()
{
for(int i=0;i<n;++i)
for(int j=0;j<m;++j)
if(!de[poi(i,j)]) dl[++tail]=poi(i,j),can[poi(i,j)]=true;
while(head<=tail)
{
int v=dl[head++];
for(node*p=con[v];p;p=p->next)
if(p->m==0) {
de[p->to]--;
if(!de[p->to]) dl[++tail]=p->to,can[p->to]=true;
}
}
}
bool bfs()
{
bool tmp=false;
memset(dep,-1,sizeof(dep));
head=tail=1;
dl[tail]=s;dep[s]=1;
while(head<=tail)
{
int v=dl[head++];
if(v==t) tmp=true;
for(node*p=con[v];p;p=p->next)
if(p->f<p->m&&dep[p->to]==-1)
dep[p->to]=dep[v]+1,dl[++tail]=p->to;
}
return tmp;
}
int dinic(int v,int e)
{
int o=0,temp=0;
if(dep[v]==-1) return 0;
if(v==t) return e;
for(node*p=con[v];p;p=p->next){
if(dep[p->to]==dep[v]+1&&p->f<p->m)
{
o=dinic(p->to,min(e-temp,p->m-p->f));
temp+=o;
p->f+=o;
p->rev->f-=o;
}
if(temp==e) break;
}
if(temp==0) dep[v]=-1;
return temp;
}
int main()
{
scanf("%d%d",&n,&m);
s=0;t=n*m+1;
for(int i=0;i<n;++i)
for(int j=0;j<m;++j)
{
int num,x,y;
scanf("%d%d",&pts[poi(i,j)],&num);
for(int k=1;k<=num;++k)
scanf("%d%d",&x,&y),addedge(poi(x,y),poi(i,j),inf),de[poi(x,y)]++;
if(j!=m-1) addedge(poi(i,j),poi(i,j+1),inf),de[poi(i,j)]++;
}
toposort();
for(int i=0;i<n;++i)
for(int j=0;j<m;++j)
if(can[poi(i,j)]) {
if(pts[poi(i,j)]>0) addedge(s,poi(i,j),pts[poi(i,j)]),ans+=pts[poi(i,j)];
else addedge(poi(i,j),t,-pts[poi(i,j)]);}
while(bfs())
ans-=dinic(s,inf);
cout<<ans;
return 0;
}