若a保护b,则a向b连边
发现保护关系若形成环,则环以及环间接保护都不可攻击
删去这些点,然后就是最大权闭合子图模型
若v[x]<0 S->x 权-v[x]
否则 x-T 权v[x]
若a保护b则 a-> b 权inf
答案是正权和-flow
#include <cstring>
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <queue>
#include <vector>
#include <iostream>
using namespace std;
#define maxn 444444
#define INF 0x3f3f3f3f
struct node
{
int u,v,f;
}e[maxn];
int st,ed,en,first[maxn],dis[maxn],next[maxn];
int num,first2[maxn],to[maxn],in[maxn],next2[maxn];
int m,n,score[maxn],vis[maxn];
int getint()
{
int res,f=1;char c;
while(c=getchar(),c<'0'||c>'9')
if(c=='-') f=-1;
res=c-'0';
while(c=getchar(),c>='0'&&c<='9')
res=res*10+c-'0';
return res*f;
}
int getnum(int x,int y)
{
return x*m+y+1;
}
void init()
{
memset(first,-1,sizeof(first));
en=-1;
st=m*n+1;
ed=m*n+2;
}
void getg(int a,int b)
{
num++;
to[num]=b;
next2[num]=first2[a];
first2[a]=num;
}
void add(int a,int b,int c)
{
en++;
e[en].v=b;
e[en].f=c;
next[en]=first[a];
first[a]=en;
en++;
e[en].v=a;
e[en].f=0;
next[en]=first[b];
first[b]=en;
}
bool bfs()
{
queue<int>q;
memset(dis,-1,sizeof(dis));
q.push(st);
dis[st]=0;
while(!q.empty())
{
int u=q.front();
q.pop();
for(int i=first[u];i!=-1;i=next[i])
{
int v=e[i].v;
if(dis[v]!=-1||e[i].f==0) continue;
dis[v]=dis[u]+1;
if(v==ed)
{
return true;
}
q.push(v);
}
}
return false;
}
int dfs(int x,int mx)
{
if(mx==0||x==ed) return mx;
int tmp,flow=0,res=0;
for(int i=first[x];i!=-1;i=next[i])
{
int v=e[i].v;
if(e[i].f==0) continue;
if(dis[v]!=dis[x]+1) continue;
tmp=dfs(v,min(mx,e[i].f));
//if(tmp==0) continue;
flow+=tmp;
e[i].f-=tmp;
e[i^1].f+=tmp;
mx-=tmp;
if(!mx) break;
}
if(!flow) dis[x]=-1;
return flow;
}
int dinic()
{
int maxflow=0,tmp=0;
while(bfs())
{
while(tmp=dfs(st,INF)) maxflow+=tmp;
}
return maxflow;
}
void dfs2(int x)
{
vis[x]=1;
for(int i=first[x];i;i=next[i])
if(!vis[to[i]])
dfs2(to[i]);
}
void topsort()
{
queue<int>q;
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
if(in[getnum(i,j)]==0)
{
q.push(getnum(i,j));
}
else
{
vis[getnum(i,j)]=1;
}
}
}
while(!q.empty())
{
int u=q.front();
q.pop();
vis[u]=0;
for(int i=first2[u];i;i=next2[i])
{
int v=to[i];
in[v]--;
if(in[v]==0)
{
q.push(v);
}
}
}
for(int i=1;i<=n*m;i++)
{
if(vis[i]) dfs2(i);
}
}
int main()
{
n=getint();
m=getint();
init();
for(int i=0;i<n;i++)
{
for(int j=0;j<m-1;j++)
{
getg(getnum(i,j+1),getnum(i,j));
in[getnum(i,j)]++;
}
}
int a,b,c;
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
score[getnum(i,j)]=getint();
a=getint();
for(int k=1;k<=a;k++)
{
b=getint();
c=getint();
getg(getnum(i,j),getnum(b,c));
in[getnum(b,c)]++;
}
}
}
topsort();
int sum=0;
for(int i=1;i<=n*m;i++)
if(!vis[i])
{
if(score[i]>0) sum+=score[i],add(i,ed,score[i]);
else add(st,i,-score[i]);
for(int j=first2[i];j;j=next2[j])
if(!vis[to[j]])
add(i,to[j],INF);
}
printf("%d\n",sum-dinic());
return 0;
}