• [bzoj1458]士兵占领


    首先在所有点上放上士兵,如果初始不合法直接输出,否则考虑删除士兵。

    对于每一个士兵,向所在行和所在列连边,每一行/列向汇点流最多能删掉多少个士兵,源点向每一个士兵流1的边,最后最大流即删掉的士兵。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define N 205
     4 #define ll long long
     5 #define inf 0x3f3f3f3f
     6 struct ji{
     7     int nex,to,len;
     8 }edge[N*N];
     9 queue<int>q;
    10 int E,n,m,k,x,y,a[N],b[N],d[N],head[N],work[N],vis[N][N];
    11 void add(int x,int y,int z){
    12     edge[E].nex=head[x];
    13     edge[E].to=y;
    14     edge[E].len=z;
    15     head[x]=E++;
    16     if (E&1)add(y,x,0); 
    17 }
    18 bool bfs(){
    19     q.push(0);
    20     memset(d,-1,sizeof(d));
    21     d[0]=0;
    22     while (!q.empty()){
    23         int k=q.front();
    24         q.pop();
    25         for(int i=head[k];i!=-1;i=edge[i].nex)
    26             if ((edge[i].len)&&(d[edge[i].to]<0)){
    27                 d[edge[i].to]=d[k]+1;
    28                 q.push(edge[i].to);
    29             }
    30     }
    31     return d[n+m+1]>=0;
    32 }
    33 int dfs(int k,int s){
    34     if (k==n+m+1)return s;
    35     int p;
    36     for(int &i=work[k];i!=-1;i=edge[i].nex)
    37         if ((edge[i].len)&&(d[edge[i].to]==d[k]+1)){
    38             p=dfs(edge[i].to,min(s,edge[i].len));
    39             if (p){
    40                 edge[i].len-=p;
    41                 edge[i^1].len+=p;
    42                 return p;
    43             }
    44         }
    45     return 0;
    46 }
    47 int dinic(){
    48     int k,ans=0;
    49     while (bfs()){
    50         memcpy(work,head,sizeof(work));
    51         while (k=dfs(0,inf))ans+=k;
    52     }
    53     return ans;
    54 }
    55 int main(){
    56     scanf("%d%d%d",&n,&m,&k);
    57     memset(head,-1,sizeof(head));
    58     for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    59     for(int i=1;i<=m;i++)scanf("%d",&b[i]);
    60     for(int i=1;i<=k;i++){
    61         scanf("%d%d",&x,&y);
    62         if ((++a[x]>m)||(++b[y]>n)){
    63             printf("JIONG!");
    64             return 0;
    65         }
    66         vis[x][y]=1;
    67     }
    68     for(int i=1;i<=n;i++)add(0,i,m-a[i]);
    69     for(int i=1;i<=n;i++)
    70         for(int j=1;j<=m;j++)
    71             if (!vis[i][j])add(i,j+n,1);
    72     for(int i=1;i<=m;i++)add(i+n,n+m+1,n-b[i]);
    73     printf("%d",n*m-k-dinic());
    74 }
    View Code
  • 相关阅读:
    用一条UPDATE语句交换两列的值
    js之事件冒泡和事件捕获详细介绍
    C# String与string的区别
    setTimeout()和setInterval()方法的区别?
    jQuery的.bind()、.live()和.delegate()之间区别
    在Hyper-V虚拟机中使用Wi-Fi上网
    调整框架的尺寸,是否显示滚动条,跳出框架
    调整框架的尺寸
    查看jquery绑定的事件函数
    Onload,Onunload,onbeforeunload,$(window).load(function() {})和$(document).ready(function(){})
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/11249596.html
Copyright © 2020-2023  润新知