关闭

[bzoj1458]士兵占领

364人阅读 评论(0) 收藏 举报
分类:

题目大意

有N*M的网格,有一些障碍格子,障碍格子不能放士兵。
非障碍格子最多放一个士兵,请放置最少的士兵使得第i行至少有a[i]个士兵第i列至少有b[i]个士兵。

上下界最小流

很明显了,第i行用点i表示,第i列用点i’表示。(i,j)不是障碍格子,那么i向j’连下限为0上限为1的边。
第i行如果需要至少j个士兵,s向i连下限为j上限为inf的边。
第i列如果需要至少j个士兵,i’向t连下限为j上限为inf的边。
然后做最小流。
要判无解的情况,我们可以做完最小流后再去检验是否有可行流。

#include<cstdio>
#include<algorithm>
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
const int maxn=300+10,maxm=50000+10,inf=10000000;
int d[maxn],h[maxn],now[maxn],go[maxm*2],dis[maxm*2],next[maxm*2],fx[maxm*2];
bool bz[maxn],pd[maxn][maxn];
int i,j,k,l,r,s,t,ss,tt,n,m,p,ans,tot;
bool czy;
void add(int x,int y,int z,int d){
    go[++tot]=y;
    dis[tot]=z;
    fx[tot]=tot+d;
    next[tot]=h[x];
    h[x]=tot;
}
void link(int x,int y,int l,int r){
    add(ss,y,l,1);
    add(y,ss,0,-1);
    add(x,tt,l,1);
    add(tt,x,0,-1);
    add(x,y,r-l,1);
    add(y,x,0,-1);
}
int dfs(int x,int flow){
    bz[x]=1;
    if (x==tt){
        ans+=flow;
        return flow;
    }
    int r=now[x],k;
    while (r){
        if (!bz[go[r]]&&dis[r]&&d[x]==d[go[r]]+1){
            k=dfs(go[r],min(flow,dis[r]));
            if (k){
                dis[r]-=k;
                dis[fx[r]]+=k;
                now[x]=r;
                return k;
            }
        }
        r=next[r];
    }
    now[x]=0;
    return 0;
}
bool change(){
    int tmp=inf,i,r;
    fo(i,ss,tt)
        if (bz[i]){
            r=h[i];
            while (r){
                if (!bz[go[r]]&&dis[r]&&d[go[r]]+1-d[i]<tmp) tmp=d[go[r]]+1-d[i];
                r=next[r];
            }
        }
    if (tmp==inf) return 0;
    fo(i,ss,tt)
        if (bz[i]) d[i]+=tmp;
    return 1;
}
int main(){
    scanf("%d%d%d",&n,&m,&p);
    ss=1;s=2;t=n+m+2;tt=n+m+3;
    fo(i,1,n){
        scanf("%d",&j);
        link(s,i+2,j,inf);
    }
    fo(i,1,m){
        scanf("%d",&j);
        link(i+n+2,t,j,inf);
    }
    fo(i,1,p){
        scanf("%d%d",&j,&k);
        pd[j][k]=1;
    }
    fo(i,1,n)
        fo(j,1,m)
            if (!pd[i][j]) link(i+2,j+n+2,0,1);
    do{
        fo(i,ss,tt) now[i]=h[i];
        fill(bz+ss,bz+tt+1,0);
        while (dfs(ss,inf)) fill(bz+ss,bz+tt+1,0);
    }while (change());
    ans=0;
    //fill(d+ss,d+tt+1,0);
    link(t,s,0,inf);
    do{
        fo(i,ss,tt) now[i]=h[i];
        fill(bz+ss,bz+tt+1,0);
        while (dfs(ss,inf)) fill(bz+ss,bz+tt+1,0);
    }while (change());
    czy=1;
    r=h[ss];
    while (r){
        if (dis[r]){
            czy=0;
            break;
        }
        r=next[r];
    }
    if (czy) printf("%d\n",ans);else printf("JIONG!\n");
}
0
0
查看评论

[BZOJ1458]士兵占领(最大流)

深谋若谷,深交若水,深明大义,深悉小节,已然,静舒。
  • Clove_unique
  • Clove_unique
  • 2016-04-06 09:28
  • 464

【bzoj1458】士兵占领 最大流

转化一下就可以了。 用的最少——不用的最多 num1[i]表示第i行有多少个没有障碍的格子 num2[i]表示第i列有多少个没有障碍的格子 源点S向第i行连一条容量为num1[i]-l[i]的边 第i列向汇点T连一条容量为num2[i]-c[i]的边 如果第i行第j列没有障碍,则从第i行...
  • u012288458
  • u012288458
  • 2016-02-21 15:22
  • 658

bzoj 1458: 士兵占领 网络流

题目Description有一个M * N的棋盘,有的格子是障碍。现在你要选择一些格子来放置一些士兵,一个格子里最多可以放置一个士兵,障碍格里不能放置士兵。我们称这些士兵占领了整个棋盘当满足第i行至少放置了Li个士兵, 第j列至少放置了Cj个士兵。现在你的任务是要求使用最少个数的士兵来占领整个棋盘。...
  • qq_33229466
  • qq_33229466
  • 2016-10-30 12:28
  • 203

【bzoj1458】【士兵占领】【网络流】

Description 有一个M * N的棋盘,有的格子是障碍。现在你要选择一些格子来放置一些士兵,一个格子里最多可以放置一个士兵,障碍格里不能放置士兵。我们称这些士兵占领了整个棋盘当满足第i行至少放置了Li个士兵, 第j列至少放置了Cj个士兵。现在你的任务是要求使用最少个数的士兵来占领整个棋...
  • sunshinezff
  • sunshinezff
  • 2016-04-19 08:52
  • 307

bzoj1458 士兵占领

有源汇有上下界最小流——且将新火试新茶,诗酒趁年华
  • AaronGZK
  • AaronGZK
  • 2015-12-26 23:42
  • 1352

【BZOJ1458】士兵占领【最大流】

【题目链接】 因为求的是最少,那么要转化成反面思路才可以最大流。 假设现在全部放满,那么可以求最多可以拿走多少。 源点向行连边,容量表示最多可以拿走多少。 列向汇点连边,容量同上。 如果一个点(x, y)可以拿走,那么x行向y列连容量为1的边。 跑最大流,结果一减就行。 /* ...
  • BraketBN
  • BraketBN
  • 2016-04-01 20:27
  • 224

【loj6257】「CodePlus 2017 12 月赛」可做题2

题目描述 “codeplus比赛的时候在做什么?有没有空?能来解决丢番图方程问题吗?”sublinekelzrip这样问qmqmqm。当然,qmqmqm并不会丢番图方程问题,所以sublinekelzrip改为提出了另一个题目,现在请你帮助qmqmqm解决这个题目。这个问题是这样的:若一个数列aa...
  • w_yqts
  • w_yqts
  • 2017-12-24 18:33
  • 153

网络流初学整合

首先说明,此篇博客是我在初学网络流时将看到过的所有很好很经典博客里简单易懂或者精彩的部分摘取组合而成的。每一篇博客侧重点不同,有些讲的比较粗略但是另一些博客很详细,所以我觉得将这些精华聚合在一起还是很重要的,每篇博客我都会标明出处。另外有些地方我也会增加一些我自己的见解,如果有不对的地方,希望各位大...
  • qq_34374664
  • qq_34374664
  • 2017-07-18 00:18
  • 284

BZOJ1458: 士兵占领 最大流

1458: 士兵占领 Time Limit: 10 Sec  Memory Limit: 64 MB Submit: 917  Solved: 515 [Submit][Status][Discuss] ...
  • Oakley_
  • Oakley_
  • 2016-09-14 15:37
  • 171

【bzoj1458】士兵占领 最大流

又是反过来考虑。。。。。 直接计算会很复杂(毕竟每一行和每一列都会有一定的限制条件,很难同时满足),那么我们放过来思考,先把所有的各自都放上士兵一共n*m-k个,然后考虑拿走一部分士兵。 源点向每行建边,边权是:m-L[i]-这一行的障碍格子数目,即是能够拿走的士兵数目,然后列向汇点建边,同理,每一...
  • pbihao
  • pbihao
  • 2017-01-15 21:57
  • 80
    个人资料
    • 访问:356415次
    • 积分:11933
    • 等级:
    • 排名:第1491名
    • 原创:814篇
    • 转载:4篇
    • 译文:0篇
    • 评论:211条
    最新评论
    文章分类