zoukankan      html  css  js  c++  java
  • 【bzoj1458】士兵占领(最大流||有源汇最大流)

    转载

    http://hzwer.com/2963.html

    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

    题解

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

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

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<cmath>
     5 #define T 201
     6 #define inf 0x7fffffff
     7 inline int read()
     8 {
     9     char ch=getchar();
    10     int f=1,x=0;
    11     while(!(ch>='0'&&ch<='9')){if(ch=='-')f=-1;ch=getchar();}
    12     while(ch>='0'&&ch<='9'){x=x*10+(ch-'0');ch=getchar();}
    13     return x*f;
    14 }
    15 using namespace std;
    16 int n,m,K,cnt=1,tot,ans;
    17 int l[105],c[105],a[105],b[105];
    18 bool mp[105][105];
    19 int q[205],h[205],head[205],cur[205];
    20 struct data{int to,next,v;}e[100001];
    21 void ins(int u,int v,int w)
    22 {e[++cnt].to=v;e[cnt].next=head[u];e[cnt].v=w;head[u]=cnt;}
    23 void insert(int u,int v,int w)
    24 {ins(u,v,w);ins(v,u,0);}
    25 bool bfs()
    26 {
    27     int t=0,w=1;
    28     for(int i=0;i<=T;i++)h[i]=-1;
    29     q[0]=0;h[0]=0;
    30     while(t!=w)
    31     {
    32         int now=q[t];t++;
    33         for(int i=head[now];i;i=e[i].next)
    34             if(e[i].v&&h[e[i].to]==-1)
    35             {
    36                 h[e[i].to]=h[now]+1;
    37                 q[w++]=e[i].to;
    38             }
    39     }
    40     if(h[T]==-1)return 0;
    41     return 1;
    42 }
    43 int dfs(int x,int f)
    44 {
    45     if(x==T)return f;
    46     int w,used=0;
    47     for(int i=cur[x];i;i=e[i].next)
    48     {
    49         if(e[i].v&&h[e[i].to]==h[x]+1)
    50         {
    51             w=f-used;
    52             w=dfs(e[i].to,min(e[i].v,w));
    53             e[i].v-=w;
    54             if(e[i].v)cur[x]=i;
    55             e[i^1].v+=w;
    56             used+=w;if(used==f)return f;
    57         }
    58     }
    59     if(!used)h[x]=-1;
    60     return used;
    61 }
    62 void dinic()
    63 {while(bfs()){for(int i=0;i<=T;i++)cur[i]=head[i];ans+=dfs(0,inf);}}
    64 int main()
    65 {
    66     m=read();n=read();K=read();
    67     int x,y;
    68     for(int i=1;i<=m;i++)
    69         l[i]=n-read();
    70     for(int i=1;i<=n;i++)
    71         c[i]=m-read();
    72     for(int i=1;i<=K;i++)
    73     {
    74         x=read();y=read();
    75         mp[x][y]=1;
    76         a[x]++;b[y]++;
    77         if(a[x]>l[x]){printf("JIONG!");return 0;}
    78         if(b[y]>c[y]){printf("JIONG!");return 0;}
    79     }
    80     tot=n*m-K;
    81     for(int i=1;i<=m;i++)
    82         insert(0,i,l[i]-a[i]);
    83     for(int i=1;i<=n;i++)
    84         insert(m+i,T,c[i]-b[i]); 
    85     for(int i=1;i<=m;i++)
    86         for(int j=1;j<=n;j++)
    87             if(!mp[i][j])insert(i,j+m,1);
    88     dinic();
    89     printf("%d",tot-ans);
    90     return 0;
    91 }
     1 #include <stdio.h>
     2 #include <iostream>
     3 #include <algorithm>
     4 #include <memory.h>
     5 #include <map>
     6 
     7 using namespace std;
     8 typedef long long LL;
     9 const int maxn = 400005;
    10 const int maxm = 105;
    11 const int inf = 1<<30;
    12 
    13 int n,m,K,S,T,cnt,ecnt=1,ehead[maxn],du[maxn];
    14 int g[maxm][maxm],row[maxn],col[maxn];
    15 
    16 struct edge {
    17     int u,v,vol,next;
    18 }edg[maxn];
    19 void add(int u,int v,int vol)
    20 {
    21     edg[++ecnt]=(edge){u,v,vol,ehead[u]};
    22     ehead[u]=ecnt;
    23     edg[++ecnt]=(edge){v,u,0,ehead[v]};
    24     ehead[v]=ecnt;
    25 }
    26 
    27 namespace dinic
    28 {
    29     int lab[maxn],que[maxn],head,tail;
    30     int dfs(int u,int cur,int T)
    31     {
    32         int res=0;
    33         if (u==T) return cur;
    34         for (int v,j=ehead[u];j&&res<cur;j=edg[j].next)
    35         if (edg[j].vol&&lab[v=edg[j].v]==lab[u]+1) {
    36             int tmp=dfs(v,min(cur-res,edg[j].vol),T);
    37             edg[j].vol-=tmp;edg[j^1].vol+=tmp;res+=tmp;
    38         }
    39         if (!res) lab[u]=-1;
    40         return res;
    41     }
    42     bool bfs(int S,int T)
    43     {
    44         memset(lab,-1,sizeof(int)*(cnt+1));
    45         que[head=tail=0]=S;lab[S]=0;
    46         while (head<=tail)
    47         {
    48             int u=que[head++];
    49             for (int v,j=ehead[u];j;j=edg[j].next)
    50             if (edg[j].vol&&lab[v=edg[j].v]==-1)
    51                 {lab[v]=lab[u]+1;que[++tail]=v;}
    52         }
    53         return lab[T]!=-1;
    54     }
    55     int dinic(int S,int T)
    56     {
    57         int res=0;
    58         while (bfs(S,T)) res+=dfs(S,inf,T);
    59         return res;
    60     }
    61     int main()
    62     {
    63         int sS=++cnt,sT=++cnt;
    64         int ocnt=ecnt;
    65         for (int i=1;i<sS;i++)
    66         {
    67             if (du[i]>0) add(i,sT,du[i]);
    68             if (du[i]<0) add(sS,i,-du[i]);
    69         }
    70         add(T,S,inf);dinic(sS,sT);
    71         int res=edg[ecnt].vol;
    72         for (int j=ehead[sS];j;j=edg[j].next)
    73             if (edg[j].vol) return -1;
    74         for (int j=ocnt+1;j<=ecnt;j++)
    75             edg[j].vol=0;
    76         return res-dinic(T,S);
    77         
    78     }
    79 }
    80 int main()
    81 {
    82     scanf("%d %d %d",&n,&m,&K);
    83     S=++cnt;T=++cnt;
    84     for (int i=1;i<=n;i++) row[i]=++cnt;
    85     for (int i=1;i<=m;i++) col[i]=++cnt;
    86     for (int x,i=1;i<=n;i++)
    87         scanf("%d",&x),du[row[i]]-=x,du[S]+=x,add(S,row[i],m);
    88     for (int x,i=1;i<=m;i++)
    89         scanf("%d",&x),du[col[i]]+=x,du[T]-=x,add(col[i],T,n);
    90     for (int u,v,i=1;i<=K;i++)
    91         scanf("%d %d",&u,&v),g[u][v]=1;
    92     for (int i=1;i<=n;i++)
    93     for (int j=1;j<=m;j++)
    94         if (!g[i][j]) add(row[i],col[j],1);
    95     int ans=dinic::main();
    96     if (ans!=-1) printf("%d",ans);else puts("No Solution");
    97     return 0;
    98 }
  • 相关阅读:
    mouseover和mouseenter的区别 mouseenter不会冒泡,mouseleave不会冒泡;
    2021年1月24日 命令按钮控件Button 和 单选按钮控件RadioButton 和复选框按钮
    2021年1月23日 文本框控件
    2021年1月21日 画了个注册的界面
    2021年1月29日 体温上报app03
    2021年1月18日 activity的三种状态
    2021年1月16日 秒表app
    2021年1月15日 界面跳转
    1.CSS知识点——css的引入方式
    面试题 315
  • 原文地址:https://www.cnblogs.com/agenthtb/p/7689192.html
Copyright © 2011-2022 走看看