洛谷P4311 士兵占领

题目

https://www.luogu.com.cn/problem/P4311

思路

网格+行列个数限制,很明显地可以看出是网络流的模型了,但是比较棘手的是它给定限定是下界而不是上界。

考虑上下界网络流?但是窝太蒻了不会。

但是我们可以用普通的最大流解决这道题。

可以发现,本题与常见模型的唯一区别就是"至少"和“至多”,那么,换个思路想想,“至少” \(x\) 个兵,在格数为 \(m\) 的一行是不是就意味着“至多” \(m-x\) 个空格子?

这启示我们可以以空格作为研究对象建图,这就转成了最经典的网格图行列限制问题。

用最大流跑出最多放多少新的空格,加上原来钦定的空格,就是最多的空格数,再用\(n*m\)一减就完事了。

特判一下无解的情况。

水过去了,结果上下界网络流还是不会QwQ。

代码

点击查看代码
#include<cstdio>
#include<cstdlib>
#include<queue>
#define maxe 30000
#define inf 0x3f3f3f3f
using namespace std;
int n,m,S,T;
int fst[300],nxt[maxe],cnt=0;
int MAP[101][101];
int deep[300],vis[300];
int lim1[300],lim2[300];
int c1[300],c2[300];
struct edge{
    int u,v,cap;
    edge(){}
    edge(int x,int y,int z){
        u=x,v=y,cap=z;
    }
} e[maxe];
void read(int &x){
    int ans=0;
    char c=getchar();
    while(!(c>='0'&&c<='9')) c=getchar();
    while(c>='0'&&c<='9'){
        ans=ans*10+c-'0';
        c=getchar();
    }
    x=ans;
    return;
}
void add(int x,int y,int z){
    e[++cnt]=edge(x,y,z);
    nxt[cnt]=fst[x];
    fst[x]=cnt;
}
int inv(int x){
    return (x&1)?x+1:x-1;
}
int bfs(){
    queue<int> q;
    for(int i=1;i<=T;++i) vis[i]=deep[i]=0;
    vis[S]=1;
    q.push(S);
    while(!q.empty()){
        int p=q.front();
        q.pop();
        for(int i=fst[p];i;i=nxt[i]){
            if(!e[i].cap) continue;
            if(!vis[e[i].v]){
                vis[e[i].v]=1;
                q.push(e[i].v);
                deep[e[i].v]=deep[p]+1;
            }
        }
    }
    return vis[T];
}
int dfs(int x,int flow){
    int i,tot_flow=0;
    if(x==T||!flow) return flow;
    for(i=fst[x];i;i=nxt[i]){
        if(deep[e[i].v]==deep[x]+1){
            int f=dfs(e[i].v,min(flow,e[i].cap));
            e[i].cap-=f;
            e[inv(i)].cap+=f;
            flow-=f;
            tot_flow+=f;
            if(!flow) break;
        }
    }
    return tot_flow;
}
int check(){
    int i,j;
    for(i=1;i<=n;++i){
        if(c1[i]+lim1[i]>m) return 0;
    }
    for(i=1;i<=m;++i){
        if(c2[i]+lim2[i]>n) return 0;
    }
    return 1;
}
int maxflow(){
    int flow=0;
    while(bfs()){
        flow+=dfs(S,inf);
    }
    return flow;
}
int main(){
    int i,j,k,x,y,z;
    int ans;
    read(n);read(m);read(k);
    S=n+m+1;T=S+1;
    for(i=1;i<=n;++i) read(lim1[i]);
    for(i=1;i<=m;++i) read(lim2[i]);
    for(i=1;i<=k;++i){
        read(x);read(y);
        MAP[x][y]=1;
        c1[x]++;c2[y]++;
    }
    if(!check()){
        printf("JIONG!");
        return 0;
    }
    for(i=1;i<=n;++i){
        for(j=1;j<=m;++j){
            if(MAP[i][j]^1){
                add(i,n+j,1);
                add(n+j,i,0);
            }
        }
    }
    for(i=1;i<=n;++i){
        if(m-lim1[i]-c1[i]){
            add(S,i,m-lim1[i]-c1[i]);
            add(i,S,0);
        }
    }
    for(i=1;i<=m;++i){
        if(n-lim2[i]-c2[i]){
            add(n+i,T,n-lim2[i]-c2[i]);
            add(T,n+i,0);
        }   
    }
    ans=n*m-maxflow()-k;
    printf("%d",ans);
    // system("pause");
    return 0;
}
posted @ 2022-03-17 20:07  文艺平衡树  阅读(27)  评论(0编辑  收藏  举报