P2172 [国家集训队]部落战争(最小路径覆盖)

P2172 [国家集训队]部落战争

每个点仅走一次:最小路径覆盖

套路地拆点,具体看代码中的$draw()$

流量每增加1,意味着一支军队可以多走一格,代价减少1

最后答案即为总点数$-dinic()$

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
int read(){
    char c=getchar();int x=0,f=1;
    while(c<'0'||c>'9') f=f&&(c!='-'),c=getchar();
    while('0'<=c&&c<='9') x=x*10+c-48,c=getchar();
    return f?x:-x;
}
#define M 400000
int n,m,R,C,S,T,d[M],cur[M],tt;
char q[100][100]; bool vis[M];
int Cnt=1,hd[M],nxt[M],ed[M],poi[M],val[M];
void adde(int x,int y,int v){
    nxt[ed[x]]=++Cnt; hd[x]=hd[x]?hd[x]:Cnt;
    ed[x]=Cnt; poi[Cnt]=y; val[Cnt]=v;
}
void link(int x,int y,int v){adde(x,y,v),adde(y,x,0);}
#define to poi[i]
bool Bfs(){
    memset(vis,0,sizeof(vis));
    queue <int> h; h.push(S);
    vis[S]=1; d[S]=0;
    while(!h.empty()){
        int x=h.front(); h.pop();
        for(int i=hd[x];i;i=nxt[i])
            if(!vis[to]&&val[i]>0)
                vis[to]=1,d[to]=d[x]+1,h.push(to);
    }return vis[T];
}
int Dfs(int x,int a){
    if(!a||x==T) return a;
    int F=0,f;
    for(int &i=cur[x];i;i=nxt[i])
        if(d[to]==d[x]+1&&(f=Dfs(to,min(a,val[i])))>0){
            F+=f,a-=f,val[i]-=f,val[i^1]+=f;
            if(!a) break;
        }
    return F;
}
int Dinic(){
    int re=0;
    while(Bfs()){
        for(int i=1;i<=T;++i) cur[i]=hd[i];
        re+=Dfs(S,1e9);
    }return re;
}
bool is(int x,int y){return x>0&&x<=n&&y>0&&y<=m&&q[x][y]=='.';}
int id(int x,int y){return x*m-m+y;}
void draw(int x,int y){
    int p=id(x,y); ++tt; link(S,p,1); link(p+n*m,T,1);
    if(is(x+R,y+C)) link(p,id(x+R,y+C)+n*m,1);
    if(is(x+R,y-C)) link(p,id(x+R,y-C)+n*m,1);
    if(is(x+C,y+R)) link(p,id(x+C,y+R)+n*m,1);
    if(is(x+C,y-R)) link(p,id(x+C,y-R)+n*m,1);
}
int main(){
    scanf("%d%d%d%d",&n,&m,&R,&C); S=n*m*2+1; T=S+1;
    for(int i=1;i<=n;++i) scanf("%s",q[i]+1);
    for(int i=1;i<=n;++i)
        for(int j=1;j<=m;++j)
            if(q[i][j]=='.') draw(i,j);
    printf("%d\n",tt-Dinic());
    return 0;
}

 

posted @ 2019-08-01 21:51  kafuuchino  阅读(203)  评论(0编辑  收藏  举报