题目链接:戳我
差不多就是DAG最小路径覆盖吧——拆点连边。 不会的可以看看蒟蒻的这个关于网络流的小总结qwq 最小路径覆盖(不相交)=节点个数-最大匹配 但是要注意的是这个题的节点个数不能算高山深涧的点,因为它本来就非法,自己就构不成一个路径。 代码如下:#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #include<queue> #define MAXN 100010 #define S 0 #define T 2*n*m+1 using namespace std; int n,m,t=1,r,c,nn,ans,kk; int head[MAXN],cur[MAXN],dis[MAXN]; char a[100][100]; struct Edge{int nxt,to,dis;}edge[MAXN<<1]; inline int trans(int x,int y){//cout<<(x-1)*m+y<<endl; return (x-1)*m+y;} inline void add(int from,int to,int dis) { edge[++t].nxt=head[from],edge[t].to=to,edge[t].dis=dis,head[from]=t; edge[++t].nxt=head[to],edge[t].to=from,edge[t].dis=0,head[to]=t; } inline bool bfs() { queue<int>q; memset(dis,0x3f,sizeof(dis)); memcpy(cur,head,sizeof(cur)); q.push(S);dis[S]=0; while(!q.empty()) { int u=q.front();q.pop(); for(int i=head[u];i;i=edge[i].nxt) { int v=edge[i].to; if(dis[v]==0x3f3f3f3f&&edge[i].dis) dis[v]=dis[u]+1,q.push(v); } } if(dis[T]==0x3f3f3f3f) return false; return true; } inline int dfs(int x,int f) { if(!f||x==T) return f; int used=0,w; for(int i=cur[x];i;i=edge[i].nxt) { int v=edge[i].to; cur[x]=i; if(dis[v]==dis[x]+1&&(w=dfs(v,min(f,edge[i].dis)))) { edge[i].dis-=w,edge[i^1].dis+=w; used+=w,f-=w; if(!f) break; } } return used; } inline int dinic() { int cur_ans=0; while(bfs()) cur_ans+=dfs(S,(int)1e9); return cur_ans; } inline bool check(int x,int y) { if(x<1||x>n||y<1||y>m) return false; if(a[x][y]!='.') return false; return true; } int main() { #ifndef ONLINE_JUDGE freopen("ce.in","r",stdin); #endif scanf("%d%d%d%d",&n,&m,&r,&c); nn=n*m; char g; scanf("%c",&g); for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) scanf("%c",&a[i][j]); scanf("%c",&g); } for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) { if(a[i][j]!='.') continue; kk++; if(check(i+r,j+c)) add(trans(i,j),trans(i+r,j+c)+nn,1); if(check(i+r,j-c)) add(trans(i,j),trans(i+r,j-c)+nn,1); if(check(i+c,j+r)) add(trans(i,j),trans(i+c,j+r)+nn,1); if(check(i+c,j-r)) add(trans(i,j),trans(i+c,j-r)+nn,1); } } for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) add(S,trans(i,j),1),add(trans(i,j)+nn,T,1); /*for(int i=1;i<=2*n*m;i++) { printf("i=%d:",i); for(int j=head[i];j;j=edge[j].nxt) cout<<edge[j].to<<" "; cout<<endl; }*/ ans=dinic(); //printf("ans=%d\n",ans); printf("%d\n",kk-ans); return 0; }
精彩评论