BZOJ 1458: 士兵占领 最大流

判断有没有解:让所有没有障碍的格子都放一个士兵.   

那么,题中要求最少放几个士兵,就是最多拿走几个士兵.  

而由于行和列对士兵个数都是由要求的,这就规定了拿走的士兵的上界.  

跑一个最大流来求就行了.  

code: 

#include <cstdio> 
#include <queue>
#include <algorithm> 
#include <cstring>  
#include <vector>
#define N 302   
#define inf 10005 
#define setIO(s) freopen(s".in","r",stdin) 
using namespace std;   
int s,t; 
int vis[N]; 
int d[N]; 
int gr[N][N]; 
int M[N],a[N],b[N];             
struct Edge { 
    int u,v,c; 
    Edge(int u=0,int v=0,int c=0):u(u),v(v),c(c){}  
}; 
queue<int>q;  
vector<Edge>edges;   
vector<int>G[N];  
void add(int u,int v,int c) {
    edges.push_back(Edge(u,v,c)); 
    edges.push_back(Edge(v,u,0));   
    int o=edges.size();   
    G[u].push_back(o-2); 
    G[v].push_back(o-1);       
}     
int dfs(int x,int cur) {  
    if(x==t) return cur;   
    int an=0,flow=0; 
    for(int i=0;i<G[x].size();++i) {
        Edge e=edges[G[x][i]];   
        if(e.c>0&&d[e.v]==d[x]+1) {      
            an=dfs(e.v,min(cur,e.c));    
            if(an) {
                cur-=an; 
                flow+=an;             
                edges[G[x][i]].c-=an; 
                edges[G[x][i]^1].c+=an;     
                if(!cur) break;    
            } 
        }
    }
    return flow;  
}
int bfs() {    
    memset(vis,0,sizeof(vis)); 
    d[s]=0; 
    vis[s]=1; 
    q.push(s); 
    while(!q.empty()) {
        int u=q.front(); 
        q.pop();  
        for(int i=0;i<G[u].size();++i) {
            if(edges[G[u][i]].c>0) {
                int v=edges[G[u][i]].v;   
                if(!vis[v]) {
                    vis[v]=1; 
                    d[v]=d[u]+1;   
                    q.push(v);   
                }
            }
        }
    } 
    return vis[t];  
}    
int maxflow() { 
    int re=0; 
    while(bfs()) {
        re+=dfs(s,inf);   
    } 
    return re; 
}
int main() { 
    // setIO("input");         
    int i,j,n,m,k;      
    scanf("%d%d%d",&n,&m,&k);      
    for(i=1;i<=n;++i)  scanf("%d",&a[i]); 
    for(i=1;i<=m;++i)  scanf("%d",&b[i]);  
    for(i=1;i<=k;++i) {
        int x,y; 
        scanf("%d%d",&x,&y);         
        gr[y][x]=1;      
    }
    for(i=1;i<=n;++i) { 
        int re=0; 
        for(j=1;j<=m;++j) { 
            re+=gr[i][j];  
        }   
        M[i]=m-re-a[i];   
    }   
    for(i=1;i<=m;++i) {
        int re=0; 
        for(j=1;j<=n;++j) {
            re+=gr[j][i];  
        }
        M[i+n]=n-re-b[i];   
    }
    for(i=1;i<=n+m;++i)  {
        if(M[i]<0)   {
            printf("JIONG!\n"); 
            return 0; 
        }
    } 
    s=0,t=n+m+1;  
    for(i=1;i<=n;++i) {      
        add(s,i,M[i]);   
        for(j=n+1;j<=n+m;++j) {
            add(i,j,1);   
        }
    }    
    for(i=n+1;i<=n+m;++i) {
        add(i,t,M[i]);  
    }   
    printf("%d\n",m*n-k-maxflow());   
    return 0; 
}

  

posted @ 2019-12-18 20:17  EM-LGH  阅读(161)  评论(0编辑  收藏  举报