The protection relationship in the diagram is similar to the maximum-weight closed sub-graph. That is, if you want to kill X, you have to kill the point that protects X, so x is connected to the point that protects it. Then the problem is transformed into the largest right-closing sub-graph.
But this picture is a little special ... Considering the condition of the ring, it is obvious that the ring and the point pointing at the ring are not selectable.
So we have to do a topological sort of the inverse of this graph so that we ignore these points ...
# include <cstdio># include<cstring># include<cstdlib># include<iostream># include<vector># include<queue># include<stack># include<map># include<Set># include<cmath># include<algorithm>using namespacestd;# define Lowbit (x) ( x)& (-x)) # define PI ACOs (-1.0) # define EPS 1e-9# define MOD1024523# define INF1000000000# define MEM (A, B) memset (A, B,sizeof(a) # define for (I,a,n) for(intI=a; i<=n; ++i) # define FO (I,a,n) for(intI=a; i<n; ++i) # define bug puts ("H"); # define LCH P<<1, l,mid# define RCH p<<1|1, mid+1, r# define MP make_pair# define PB push_backtypedef pair<int,int>pii;typedef Vector<int>vi;# pragma comment (linker,"/stack:1024000000,1024000000") typedefLong LongLL;intScan () {intx=0, f=1;CharCh=GetChar (); while(ch<'0'|| Ch>'9'){if(ch=='-') f=-1; ch=GetChar ();} while(ch>='0'&&ch<='9') {x=x*Ten+ch-'0'; ch=GetChar ();} returnx*F;}voidOut (inta) {if(a<0) {Putchar ('-'); a=-A;} if(a>=Ten) Out (A/Ten); Putchar (A%Ten+'0');}Const intn=605;//Code begin ...structedge{intP, Next, W;} edge[n*N];intHead[n], cnt=2, Cost[n], dee[n], N, M, S, T, Vis[n];BOOLMark[n];queue<int>Q;vector<PII>E[n];voidAdd_edge (intUintVintW) {EDGE[CNT].P=v; Edge[cnt].w=w; Edge[cnt].next=head[u]; head[u]=cnt++; EDGE[CNT].P=u; edge[cnt].w=0; EDGE[CNT].NEXT=HEAD[V]; head[v]=cnt++;}intBFs () {intI, V; Mem (Vis,-1); Vis[s]=0; Q.push (s); while(!Q.empty ()) {v=Q.front (); Q.pop (); for(i=head[v]; i; i=Edge[i].next) { if(edge[i].w>0&& vis[edge[i].p]==-1) {VIS[EDGE[I].P]=VIS[V] +1; Q.push (EDGE[I].P); } } } returnvis[t]!=-1;}intDfsintXintLow ) { intI, A, temp=Low ; if(x==t)returnLow ; for(i=head[x]; i; i=Edge[i].next) { if(edge[i].w>0&& vis[edge[i].p]==vis[x]+1) {a=Dfs (Edge[i].p,min (edge[i].w,temp)); Temp-=a; Edge[i].w-=a; edge[i^1].W + =A; if(temp==0) Break; } } if(Temp==low) vis[x]=-1; returnlow-temp;}voidTopsort () {FO (I,0, n*m)if(!dee[i]) Q.push (i), mark[i]=true; while(!Q.empty ()) { intu=Q.front (); Q.pop (); FO (i,0, E[u].size ()) {PII v=E[u][i]; if(!v.second)Continue; --Dee[v.first]; if(!dee[v.first]) Q.push (V.first), mark[v.first]=true; } }}intMain () {intT, x, Y, res=0, TMP, sum=0; scanf ("%d%d", &n,&m); S=n*m; t=n*m+1; FO (i,0, N) FO (J,0, M) {scanf ("%d%d",&cost[i*m+j],&T); while(t--) {scanf ("%d%d", &x,&y); E[X*M+Y].PB (MP (I*m+j,0)); E[i*M+J].PB (MP (X*m+y,1)); ++dee[x*m+y]; }} FO (I,0, N) FO (J,0, M-1) FO (k,j+1, M) E[I*M+J].PB (MP (I*m+k,0), E[I*M+K].PB (MP (I*m+j,1)), ++dee[i*m+J]; Topsort (); FO (i,0Nm) {if(!mark[i])Continue; if(cost[i]>=0) res+=Cost[i], Add_edge (S,i,cost[i]); ElseAdd_edge (i,t,-Cost[i]); FO (J,0, E[i].size ()) {PII v=E[i][j]; if(v.second| |! Mark[v.first])Continue; Add_edge (I,v.first,inf); } } while(BFS ()) while(Tmp=dfs (S,inf)) sum+=tmp; printf ("%d\n", res-sum); return 0;}
View Code
Bzoj 1565 Plants vs. Zombies (topological sort + maximum weight closure sub-graph)