之前遇到过一个题,题意大概是有云,小岛,水,用二维矩阵来表示。云下面可以是小岛也可以是水,不知道是啥,然后让干啥干啥,也是网络流做。
关于染方块的比赛历程为:倒着坐,先把绿色周围的空白方块染成红色,最后再check每一个红块,看看删除它对答案造成的影响。它这个影响是很难check的,影响是相互的,结果就是wa,后来想过dp,复杂度无法接受,图论,不会建图。
正解就是网络流啦。超级源点S,超级汇点T,S向所有绿点连容量为1的边,绿点向它上下左右4个方向的白点连容量为1的边,然后这些白点再向T连容量为1的边。答案为cnt(green)+cnt(绿色周围的白点)-maxflow。
对于一个绿点而言,如果它变成白点,那么它对答案的贡献为1,如果存在一个S经它到T的流,
那么它对最大流的贡献为1,随之把自己对答案的贡献消掉了。也就是有maxflow数量的绿点一定是需要把周围一个白点变红的,剩下的绿点都流不出去,也就能对答案产生真正的一个贡献。
#include <bits/stdc++.h> #define inf 233333333 #define N 500010 #define p(a) putchar(a) #define For(i,a,b) for(int i=a;i<=b;++i) //by war //2020.11.17 using namespace std; int n,m,x,y,v,maxflow,tot,cnt,ans; int head[N],deep[N],cur[N],num[100][100]; int X[]={-1,1,0,0}; int Y[]={0,0,1,-1}; char a[100][100]; struct node{ int n; int v; int next; }e[N]; queue<int>q; void in(int &x){ int y=1;char c=getchar();x=0; while(c<'0'||c>'9'){if(c=='-')y=-1;c=getchar();} while(c<='9'&&c>='0'){ x=(x<<1)+(x<<3)+c-'0';c=getchar();} x*=y; } void o(int x){ if(x<0){p('-');x=-x;} if(x>9)o(x/10); p(x%10+'0'); } void push(int x,int y,int v){ e[tot].n=y; e[tot].v=v; e[tot].next=head[x]; head[x]=tot++; } bool bfs(int s,int t){ memset(deep,-1,sizeof(deep)); For(i,0,cnt) cur[i]=head[i]; deep[s]=0; q.push(s); while(!q.empty()){ int now=q.front(); q.pop(); for(int i=head[now];i!=-1;i=e[i].next) if(deep[e[i].n]==-1 && e[i].v>0){ deep[e[i].n]=deep[now]+1; q.push(e[i].n); } } return deep[t]!=-1; } int dfs(int now,int t,int lim){ if(now==t||lim==0) return lim; int flow=0,f; for(int i=cur[now];i!=-1;i=e[i].next){ cur[now]=i; if(deep[e[i].n]==deep[now]+1 && (f=dfs(e[i].n,t, min(lim,e[i].v) ))){ flow+=f; lim-=f; e[i].v-=f; e[i^1].v+=f; if(!lim) break; } } return flow; } void dinic(int s,int t){ while(bfs(s,t)){ maxflow+=dfs(s,t,inf); } } int main(){ scanf("%s",a[1]+1); n=strlen(a[1]+1); For(i,2,n) scanf("%s",a[i]+1); memset(head,-1,sizeof(head)); For(i,1,n) For(j,1,n){ if(a[i][j]=='O'){ ++cnt; num[i][j]=cnt; push(0,cnt,1); push(cnt,0,0); } } For(i,1,n) For(j,1,n){ if(a[i][j]=='.'){ For(k,0,3){ int tempx=i+X[k],tempy=j+Y[k]; if(tempx>=1 && tempx<=n && tempy>=1 && tempy<=n && a[tempx][tempy]=='O'){ ++cnt; num[i][j]=-cnt; break; } } For(k,0,3){ int tempx=i+X[k],tempy=j+Y[k]; if(tempx>=1 && tempx<=n && tempy>=1 && tempy<=n && a[tempx][tempy]=='O'){ push(num[tempx][tempy],cnt,1); push(cnt,num[tempx][tempy],0); } } } } ++cnt; For(i,1,n) For(j,1,n){ ans+=(a[i][j]=='O' || a[i][j]=='.'); if(num[i][j]<0){ push(-num[i][j],cnt,1); push(cnt,-num[i][j],0); } } dinic(0,cnt); o(ans-maxflow); return 0; }