zoukankan      html  css  js  c++  java
  • 【BZOJ】1458: 士兵占领(上下界网络流)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1458

    是不是我脑洞太小了。。。。。。。直接弄上下界最小流。。。。。。。。(就当复习了。。

    二分图X和Y,然后如果(x,y)能放,那么连边x->y,上界1,下界0。

    然后源s->x连下界为要求的下界,上界为oo

    y->t连下界为要求下界,上界为oo。

    然后来一次上下界最小流。。

    //看了题解。。。感觉。。。。。。。。我脑洞怎么那么小。。。。将问题转换为:放满棋盘后去掉最多的士兵。搬运hzwer学长的题解:

    此题的思路是先放满棋盘,然后考虑最多可以删多少个。。。

    某一行和某一列的可以放的格子数小于需求就直接jiong掉
    然后从源向每一行连边,流量为可以放的格子数 - 需求的格子数(也就是可以删多少格子)
    从每一列向汇,同上.
    从每一个非障碍的格子的行向列连边流量为1
    跑一遍最大流即可ans=可放格子数-maxflow

    囧。。

    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <string>
    #include <iostream>
    #include <algorithm>
    #include <queue>
    #include <set>
    #include <map>
    using namespace std;
    typedef long long ll;
    #define rep(i, n) for(int i=0; i<(n); ++i)
    #define for1(i,a,n) for(int i=(a);i<=(n);++i)
    #define for2(i,a,n) for(int i=(a);i<(n);++i)
    #define for3(i,a,n) for(int i=(a);i>=(n);--i)
    #define for4(i,a,n) for(int i=(a);i>(n);--i)
    #define CC(i,a) memset(i,a,sizeof(i))
    #define read(a) a=getint()
    #define print(a) printf("%d", a)
    #define dbg(x) cout << (#x) << " = " << (x) << endl
    #define error(x) (!(x)?puts("error"):0)
    #define rdm(x, i) for(int i=ihead[x]; i; i=e[i].next)
    inline const int getint() { int r=0, k=1; char c=getchar(); for(; c<'0'||c>'9'; c=getchar()) if(c=='-') k=-1; for(; c>='0'&&c<='9'; c=getchar()) r=r*10+c-'0'; return k*r; }
    
    const int N=305, oo=~0u>>1;
    int ihead[N], cnt=1;
    struct dat { int next, to, from, cap; }e[N*N*2];
    void add(int u, int v, int c) {
    	e[++cnt].next=ihead[u]; ihead[u]=cnt; e[cnt].from=u; e[cnt].to=v; e[cnt].cap=c;
    	e[++cnt].next=ihead[v]; ihead[v]=cnt; e[cnt].from=v; e[cnt].to=u; e[cnt].cap=0;
    }
    int p[N], d[N], gap[N], cur[N];
    int isap(int s, int t, int n) {
    	for1(i, 0, n) p[i]=0, d[i]=0, gap[i]=0, cur[i]=ihead[i];
    	gap[0]=n; int ret=0, f, u=s, i;
    	while(d[s]<n) {
    		for(i=cur[u]; i; i=e[i].next) if(e[i].cap && d[e[i].to]+1==d[u]) break;
    		if(i) {
    			p[e[i].to]=cur[u]=i; u=e[i].to;
    			if(u==t) {
    				for(f=oo; u!=s; u=e[p[u]].from) f=min(f, e[p[u]].cap);
    				for(u=t; u!=s; u=e[p[u]].from) e[p[u]].cap-=f, e[p[u]^1].cap+=f;
    				ret+=f;
    			}
    		}
    		else {
    			if(!(--gap[d[u]])) break;
    			d[u]=n; cur[u]=ihead[u];
    			for(i=ihead[u]; i; i=e[i].next) if(e[i].cap && d[e[i].to]+1<d[u]) d[u]=d[e[i].to]+1;
    			++gap[d[u]];
    			if(u!=s) u=e[p[u]].from;
    		}
    	}
    	return ret;
    }
    
    int n, m, k, x[N], y[N], vis[N][N], in[N];
    #define X(i) (i)
    #define Y(i) (n+i)
    int main() {
    	read(n); read(m); read(k); int s=n+m+1, t=s+1;
    	for1(i, 1, n) read(x[i]);
    	for1(i, 1, m) read(y[i]);
    	for1(i, 1, k) { int u=getint(), v=getint(); vis[u][v]=1; }
    	for1(i, 1, n) for1(j, 1, m) if(!vis[i][j]) add(X(i), Y(j), 1);
    
    	int S=t+1, T=S+1;
    	for1(i, 1, n) in[X(i)]+=x[i], in[s]-=x[i];
    	for1(i, 1, m) in[t]+=y[i], in[Y(i)]-=y[i];
    	for1(i, 0, T) if(in[i]>0) add(S, i, in[i]); else if(in[i]<0) add(i, T, -in[i]);
    
    	isap(S, T, T);
    	add(t, s, oo);
    	int ans=isap(S, T, T);
    	rdm(S, i) if(e[i].cap) { puts("JIONG!"); return 0; }
    	print(ans);
    	return 0;
    }
    

      


    Description

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

    Input

    第一行两个数M, N, K分别表示棋盘的行数,列数以及障碍的个数。 第二行有M个数表示Li。 第三行有N个数表示Ci。 接下来有K行,每行两个数X, Y表示(X, Y)这个格子是障碍。

    Output

    输出一个数表示最少需要使用的士兵个数。如果无论放置多少个士兵都没有办法占领整个棋盘,输出”JIONG!” (不含引号)

    Sample Input

    4 4 4
    1 1 1 1
    0 1 0 3
    1 4
    2 2
    3 3
    4 3

    Sample Output

    4
    数据范围
    M, N <= 100, 0 <= K <= M * N

    HINT

     

    Source

  • 相关阅读:
    分享:TreeFrog 1.3 发布,基于 C++/QT 的 Web 框架
    Linux环境进程间通信(五): 共享内存(上)
    TUP第二期:架构师王鹏云演讲实录 _业界_科技时代_新浪网
    发布我的倒排索引 C/C++ ChinaUnix.net
    操作系统内存管理——分区、页式、段式管理
    内存管理内幕
    IT农民工如何来美国工作
    来自 王斌 (@iwangbin) 的推文
    ScheduledExecutorService执行周期性或定时任务
    PHP XML parse error: Extra content at the end of the document
  • 原文地址:https://www.cnblogs.com/iwtwiioi/p/4153061.html
Copyright © 2011-2022 走看看