反向最大闭合图+topsort;
题解:
1.从右往左链接相邻的植物;
2.引有向边保护-->被保护;
3.处理环;
4.负权连s,正权连t;
5.跑最大流;
#include<iostream> #include<cstdio> #include<cstring> #define maxx 10000000 using namespace std; int read() { int f=1,x=0; char ch; ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();} return x*f; } int sum=0; int st,ed; int n,m; int tot=0; int vis[10000]; int level[10000]; int map[1000][1000]; int ww[600][500]; int c[100000]; int v[100000]; struct {int flow,next,y;}e[1000000]; int len=0; int re[1000000]; int q[1000000],le[1000000],head,tail,lin[10000000]; void init(int x,int y,int flow) { vis[y]++; e[++len].flow=flow;e[len].y=y;e[len].next=lin[x];lin[x]=len;re[len]=len+1; e[++len].flow=0;e[len].y=x;e[len].next=lin[y];lin[y]=len;re[len]=len-1; return ; } void initx() { st=++tot; n=read();m=read(); for(int i=0;i<=n-1;i++)for(int u=0;u<=m-1;u++){map[i][u]=++tot;if(u-1>=0)init(map[i][u],map[i][u-1],maxx);} ed=++tot; for(int i=0;i<=n-1;i++) { for(int u=0;u<=m-1;u++) { v[map[i][u]]=read(); int w=read(); for(int z=1;z<=w;z++) { int x,y; x=read(); y=read(); init(map[i][u],map[x][y],maxx); } } } } int f[1000000]; void topsort() { head=0;tail=0; for(int i=map[0][0];i<=map[n-1][m-1];i++) if(vis[i]==0)q[++tail]=i; while(head++<tail) { int x=q[head]; for(int i=lin[x];i;i=e[i].next) { if(e[i].flow<=0)continue; int y=e[i].y; vis[y]--; if(vis[y]==0)q[++tail]=y; } } for(int i=1;i<=tail;i++) { f[q[i]]=1; if(v[q[i]]>=0){init(q[i],ed,v[q[i]]),sum+=v[q[i]];} else init(st,q[i],-v[q[i]]); } } bool makelevel() { f[st]=1; f[ed]=1; memset(level,-1,sizeof(level)); head=0;tail=1; q[1]=st;level[st]=0; while(head++<tail) { int x=q[head]; for(int i=lin[x];i;i=e[i].next) { int y=e[i].y; if(e[i].flow<=0)continue; if(f[y]==0)continue; if(level[y]==-1) { level[y]=level[x]+1; q[++tail]=y; } } } //cout<<"s"; return level[ed]!=-1; } int maxlow(int x,int flow) { if(x==ed)return flow; int maax=0; int d; for(int i=lin[x];i&&maax<flow;i=e[i].next) { int y=e[i].y; if(f[y]==0)continue; if(e[i].flow<=0)continue; if(level[y]!=level[x]+1)continue; if(d=maxlow(y,min(flow-maax,e[i].flow))) { maax+=d; e[i].flow-=d; e[re[i]].flow+=d; } } if(maax==0)level[x]=-1; return maax; } int ans=0; void dinic() { int d; while(makelevel()) while(d=maxlow(st,maxx)) { ans+=d; } } int main() { initx(); topsort(); memset(q,0,sizeof(q)); dinic(); cout<<sum-ans<<endl; return 0; }