zoukankan      html  css  js  c++  java
  • 洛谷P4311 士兵占领

    题目链接:https://www.luogu.org/problemnew/show/P4311

    知识点:  最大流

    解题思路:

      对于每一行,建立一条从源点到该行的边,容量为这一行能不放置士兵的点数;

      对于每一列,建立一条从该列到汇点的边,容量为这一列能不放置士兵的点数;

      对于每一个没有障碍的点 ((x,y)),建立一条从第 (x) 行到第 (y) 列的边,容量为 (1)。

      从源点到汇点的最大流即为图上可以不放置士兵的最大点数,答案即为图上可以放置士兵的点数减去最大流。

    AC代码:

      

      1 #include <bits/stdc++.h>
      2 
      3 using namespace std;
      4 const int maxn=110;
      5 int L[maxn],C[maxn];
      6 bool zhang[maxn][maxn];
      7 
      8 const int MAXN = 510;//点数的最大值
      9 const int MAXM = 15000;//边数的最大值
     10 const int INF = 0x3f3f3f3f;
     11 struct Edge{
     12     int to,next,cap,flow;
     13 }edge[MAXM];//注意是MAXM
     14 int tol;
     15 int head[MAXN];
     16 int gap[MAXN],dep[MAXN],cur[MAXN];
     17 void init(){
     18     tol = 0;
     19     memset(head,-1,sizeof(head));
     20 }
     21 void addedge(int u,int v,int w,int rw = 0){
     22     edge[tol].to = v; edge[tol].cap = w; edge[tol].flow = 0;
     23     edge[tol].next = head[u]; head[u] = tol++;
     24     edge[tol].to = u; edge[tol].cap = rw; edge[tol].flow = 0;
     25     edge[tol].next = head[v]; head[v] = tol++;
     26 }
     27 int Q[MAXN];
     28 void BFS(int start,int end){
     29     memset(dep,-1,sizeof(dep));
     30     memset(gap,0,sizeof(gap));
     31     gap[0] = 1;
     32     int front = 0, rear = 0;
     33     dep[end] = 0;
     34     Q[rear++] = end;
     35     while(front != rear){
     36         int u = Q[front++];
     37         for(int i = head[u]; i != -1; i = edge[i].next){
     38             int v = edge[i].to;
     39             if(dep[v] != -1)
     40                 continue;
     41             Q[rear++] = v;
     42             dep[v] = dep[u] + 1;
     43             gap[dep[v]]++;
     44         }
     45     }
     46 }
     47 int S[MAXN];
     48 int sap(int start,int end,int N){
     49     BFS(start,end);
     50     memcpy(cur,head,sizeof(head));
     51     int top = 0;
     52     int u = start;
     53     int ans = 0;
     54     while(dep[start] < N){
     55         if(u == end){
     56             int Min = INF;
     57             int inser;
     58             for(int i = 0;i < top;i++)
     59                 if(Min > edge[S[i]].cap - edge[S[i]].flow){
     60                     Min = edge[S[i]].cap - edge[S[i]].flow;
     61                     inser = i;
     62                 }
     63             for(int i = 0;i < top;i++){
     64                 edge[S[i]].flow += Min;
     65                 edge[S[i]^1].flow -= Min;
     66             }
     67             ans += Min;
     68             top = inser;
     69             u = edge[S[top]^1].to;
     70             continue;
     71         }
     72         bool flag = false;
     73         int v;
     74         for(int i = cur[u]; i != -1; i = edge[i].next){
     75             v = edge[i].to;
     76             if(edge[i].cap - edge[i].flow && dep[v]+1 == dep[u]){
     77                 flag = true;
     78                 cur[u] = i;
     79                 break;
     80             }
     81         }
     82         if(flag){
     83             S[top++] = cur[u];
     84             u = v;
     85             continue;
     86         }
     87         int Min = N;
     88         for(int i = head[u]; i != -1; i = edge[i].next)
     89             if(edge[i].cap - edge[i].flow && dep[edge[i].to] < Min){
     90                 Min = dep[edge[i].to];
     91                 cur[u] = i;
     92             }
     93         gap[dep[u]]--;
     94         if(!gap[dep[u]])
     95             return ans;
     96         dep[u] = Min + 1;
     97         gap[dep[u]]++;
     98         if(u != start)
     99             u = edge[S[--top]^1].to;
    100     }
    101     return ans;
    102 }
    103 int lie[110],han[110];
    104 int main(){
    105     int M,N,K;
    106     scanf("%d%d%d",&N,&M,&K);
    107     int s=0,t=MAXN-1;
    108     init();
    109     for(int i=1;i<=N;i++){
    110         scanf("%d",&L[i]);
    111     //    addedge(s,i,L[i]);
    112         han[i]=M;
    113     }
    114     for(int i=1;i<=M;i++){
    115         scanf("%d",&C[i]);
    116     //    addedge(i+N,t,C[i]);
    117         lie[i]=N;
    118     }
    119     int sum=N*M;
    120     for(int i=0;i<K;i++){
    121         int x,y;
    122         scanf("%d%d",&x,&y);
    123         zhang[x][y]=true;
    124         sum--;
    125         lie[y]--,han[x]--;
    126     }
    127     for(int i=1;i<=M;i++){
    128         if(lie[i]<C[i]){
    129             printf("JIONG!
    ");
    130             return 0;
    131         }
    132         addedge(i+N,t,lie[i]-C[i]);
    133     }
    134     for(int i=1;i<=N;i++){
    135         if(han[i]<L[i]){
    136             printf("JIONG!
    ");
    137             return 0;
    138         }
    139         addedge(s,i,han[i]-L[i]);
    140     }//特判 "JIONG" 的情况
    141 
    142     for(int i=1;i<=N;i++){
    143         for(int j=1;j<=M;j++){
    144             if(!zhang[i][j])
    145                 addedge(i,j+N,1);
    146         }
    147     }
    148     int saps=sap(s,t,N+M+2);
    149     printf("%d
    ",sum-saps);
    150     return 0;
    151 }
    “这些年我一直提醒自己一件事情,千万不要自己感动自己。大部分人看似的努力,不过是愚蠢导致的。什么熬夜看书到天亮,连续几天只睡几小时,多久没放假了,如果这些东西也值得夸耀,那么富士康流水线上任何一个人都比你努力多了。人难免天生有自怜的情绪,唯有时刻保持清醒,才能看清真正的价值在哪里。”
  • 相关阅读:
    常用网站
    我的第一个 python 爬虫脚本
    在文件夹下所有文件中查找字符串(linux/windows)
    Python 列表 insert() 方法
    mysql 替换 tab 键 ( )
    访问权限的修饰符
    eclipse 快捷键
    位运算
    hadoop 环境搭建
    Hadoop 快速入门
  • 原文地址:https://www.cnblogs.com/Blogggggg/p/9057440.html
Copyright © 2011-2022 走看看