http://www.lydsy.com/JudgeOnline/problem.php?id=1565
思路:由于植物之间有保护关系:(右边的植物保护左边的植物,植物攻击范围内的植物都被保护了),因此可以用最大权闭合子图。
1 #include<algorithm> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstring> 5 #include<iostream> 6 #define inf 0x7fffffff 7 struct edge{ 8 int u,v; 9 }e[500005]; 10 int tot,go[500005],first[500005],next[500005],flow[500005]; 11 int op[500005],cnt[500005],dis[500005],n,m,mx[20005],all,ru[500005]; 12 int id[105][105],w[105][105],S,T,nodes,pd[500005],c[500005]; 13 int read(){ 14 int t=0,f=1;char ch=getchar(); 15 while (ch<'0'||ch>'9') {if (ch=='-') f=-1;ch=getchar();} 16 while ('0'<=ch&&ch<='9'){t=t*10+ch-'0';ch=getchar();} 17 return t*f; 18 } 19 void insert(int x,int y,int z){ 20 tot++; 21 go[tot]=y; 22 next[tot]=first[x]; 23 first[x]=tot; 24 flow[tot]=z; 25 } 26 void add(int x,int y,int z){ 27 insert(x,y,z);op[tot]=tot+1; 28 insert(y,x,0);op[tot]=tot-1; 29 } 30 int dfs(int x,int f){ 31 if (x==T) return f; 32 int sum=0,mn=nodes; 33 for (int i=first[x];i;i=next[i]){ 34 int pur=go[i]; 35 if (flow[i]&&dis[pur]+1==dis[x]){ 36 int save=dfs(pur,std::min(f-sum,flow[i])); 37 sum+=save; 38 flow[i]-=save; 39 flow[op[i]]+=save; 40 if (sum==f||dis[S]>=nodes) return sum; 41 } 42 if (flow[i]) mn=std::min(mn,dis[pur]); 43 } 44 if (sum==0){ 45 cnt[dis[x]]--; 46 if (cnt[dis[x]]==0){ 47 dis[S]=nodes; 48 }else{ 49 dis[x]=mn+1; 50 cnt[dis[x]]++; 51 } 52 } 53 return sum; 54 } 55 int main(){ 56 n=read();m=read(); 57 S=0;nodes=1; 58 for (int i=1;i<=n;i++) 59 for (int j=1;j<=m;j++) 60 id[i][j]=nodes++; 61 for (int i=1;i<=n;i++) 62 for (int j=1;j<=m;j++){ 63 w[i][j]=read(); 64 int num=read(); 65 for (int k=1;k<=num;k++){ 66 int x=read(),y=read(); 67 x++;y++; 68 e[++all].u=id[i][j],e[all].v=id[x][y],ru[e[all].v]++; 69 } 70 } 71 for (int i=1;i<=n;i++) 72 for (int j=m;j>1;j--) 73 e[++all].u=id[i][j],e[all].v=id[i][j-1],ru[id[i][j-1]]++; 74 for (int i=1;i<=all;i++) 75 insert(e[i].u,e[i].v,0); 76 T=nodes;nodes++; 77 int top=0; 78 for (int i=1;i<=nodes-1;i++) 79 if (ru[i]==0) 80 pd[i]=1,c[++top]=i; 81 while (top>0){ 82 int now=c[top--]; 83 for (int i=first[now];i;i=next[i]){ 84 int pur=go[i]; 85 ru[pur]--; 86 if (ru[pur]==0){ 87 pd[pur]=1; 88 c[++top]=pur; 89 } 90 } 91 } 92 tot=0; 93 for (int i=1;i<=nodes;i++) 94 first[i]=0; 95 for (int i=1;i<=all;i++) 96 if (pd[e[i].u]&&pd[e[i].v]) 97 add(e[i].u,e[i].v,inf); 98 int sum=0; all=0; 99 for (int i=1;i<=n;i++) 100 for (int j=1;j<=m;j++) 101 if (pd[id[i][j]]){ 102 if (w[i][j]>0) add(id[i][j],T,w[i][j]),sum+=w[i][j]; 103 else 104 if (w[i][j]<0) add(S,id[i][j],-w[i][j]); 105 all++; 106 } 107 nodes=all; 108 int ans=0; 109 while (dis[S]<nodes) ans+=dfs(S,inf); 110 printf("%d\n",sum-ans); 111 }