bzoj1458:最大流

看到了M,N<=100于是才10000个点,直接建图吧,然后想想想=>看师兄题解。。。。。

将行和列作为节点,行和S相连,列和T相连,然后不是障碍的ij相连,c=1;

关键是能想到反过来求最多可以拿走多少个士兵,就能够转换为maxflow了。

--------------------------------------------------------------------------------------

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define rep(i,n) for(int i=1;i<=n;i++)
#define clr(x,c) memset(x,c,sizeof(x))
const int inf=0x3f3f3f;
int read(){
 int x=0,f=1;char c=getchar();
 while(!isdigit(c)){
  if(c==‘-‘) f=-1;
  c=getchar();
 }
 while(isdigit(c)){
  x=x*10+c-‘0‘;
  c=getchar();
 }
 return x*f;
}

struct edge{
 int to,cap;
 edge *next,*rev;
};
edge e[400000],*pt=e,*cur[205],*head[205],*p[205];
int d[205],cnt[205],vis[105][105],a[105],b[105],l[105],c[105];
void add(int u,int v,int d){
 pt->to=v;
 pt->cap=d;
 pt->next=head[u];
 head[u]=pt++;
}
void adde(int u,int v,int d){
 add(u,v,d);
 add(v,u,0);
 head[u]->rev=head[v];
 head[v]->rev=head[u];
}

int maxflow(int s,int t,int n){
 int flow=0,a=inf,x=s;
 clr(d,0);
 clr(cnt,0);
 cnt[0]=n;
 while(d[s]<n){
  edge *ee;
  for(ee=cur[x];ee;ee=ee->next)
   if(ee->cap>0&&d[ee->to]+1==d[x])
     break;
     if(ee){
      p[ee->to]=cur[x]=ee;
      a=min(a,ee->cap);
      x=ee->to;
      if(x==t){
       while(x!=s){
        p[x]->cap-=a;
        p[x]->rev->cap+=a;
        x=p[x]->rev->to;
       }
       flow+=a;
       a=inf;
      }
     }
     else{
      if(!--cnt[d[x]]) break;
      d[x]=n;
      for(ee=head[x];ee;ee=ee->next){
       if(ee->cap>0&&d[ee->to]+1<d[x]){
        d[x]=d[ee->to]+1;
        cur[x]=ee;
       }
      }
      cnt[d[x]]++;
      if(x!=s) x=p[x]->rev->to;
     }
 }
 return flow;

}
int main(){
 int L=read(),C=read(),k=read(),s=0,t=L+C+1,n=t+1;
 rep(i,L) l[i]=read();
 rep(i,C) c[i]=read();
 clr(vis,1);clr(a,0);clr(b,0);
 rep(i,k){
  int u=read(),v=read();
  vis[u][v]=0;a[u]++;b[v]++;
 }
 rep(i,L) if(C-a[i]<l[i]) {
     puts("JIONG!");
     return 0;
 }
 rep(i,C) if(L-b[i]<c[i]){
     puts("JIONG!");
     return 0;
 }
 rep(i,L) adde(s,i,C-a[i]-l[i]);
 rep(i,C) adde(L+i,t,L-b[i]-c[i]);
 rep(i,L)
      rep(j,C){
       if(vis[i][j])
         adde(i,L+j,1);
      }
 printf("%d\n",L*C-k-maxflow(s,t,n));
 return 0;
}

--------------------------------------------------------------------------------------

1458: 士兵占领

Time Limit: 10 Sec  Memory Limit: 64 MB
Submit: 705  Solved: 408
[Submit][Status][Discuss]

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

[Submit][Status][Discuss

时间: 2024-10-08 12:02:16

bzoj1458:最大流的相关文章

【BZOJ-1458】士兵占领 最大流

1458: 士兵占领 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 782  Solved: 456[Submit][Status][Discuss] Description 有一个M * N的棋盘,有的格子是障碍.现在你要选择一些格子来放置一些士兵,一个格子里最多可以放置一个士兵,障碍格里不能放置士兵.我们称这些士兵占领了整个棋盘当满足第i行至少放置了Li个士兵, 第j列至少放置了Cj个士兵.现在你的任务是要求使用最少个数的士兵来占领整个棋盘.

【费用流占个坑】BZOJ1458的脑洞//n\\

[题目大意] 有一个M * N的棋盘,有的格子是障碍.现在你要选择一些格子来放置一些士兵,一个格子里最多可以放置一个士兵,障碍格里不能放置士兵.我们称这些士兵占领了整个棋盘当满足第i行至少放置了Li个士兵, 第j列至少放置了Cj个士兵.现在你的任务是要求使用最少个数的士兵来占领整个棋盘. [思路] 还没有写完..开始做了才发现这是一道权限题没地方测…………先占个坑码一下,免得过会儿忘了. 先判断是否有解,如果把棋盘全部填满的话还是不能满足,则必定是无解的:否则必定是有解.由于问的是最少要多少个士

【BZOJ1458】士兵占领 最大流的模板题

我们只要把他们可以有的限制用流量限制,再用两者关系限制一下就可以开心的跑了. #include <cstdio> #include <cstring> #include <iostream> #define r register #define N 1005 using namespace std; inline int read() { r int sum=0; r char ch=getchar(); while(ch<'0'||ch>'9')ch=ge

对IO流的操作(文件大小,拷贝,移动,删除)

import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.FileReader;import java.io.FileWriter;import java.io.IOException;import java.io.SequenceInputStream; class LjyFileClass { /*LjyFileClass工具类使用需知: * * 1.计算

hdu3461Marriage Match IV 最短路+最大流

//给一个图.给定起点和终点,仅仅能走图上的最短路 //问最多有多少种走的方法.每条路仅仅能走一次 //仅仅要将在最短路上的全部边的权值改为1.求一个最大流即可 #include<cstdio> #include<cstring> #include<iostream> #include<queue> #include<vector> using namespace std ; const int inf = 0x3f3f3f3f ; const

Java学习之IO流三

1.从键盘接收两个文件夹路径,把其中一个文件夹中(包含内容)拷贝到另一个文件夹中(高效流) 1 /** 2 * 1.从键盘接收两个文件夹路径,把其中一个文件夹中(包含内容)拷贝到另一个文件夹中 3 * @author vanguard 4 * 5 */ 6 public class Demo01 { 7 public static void main(String[] args) { 8 //键盘输入两个文件夹路径 9 Scanner sc = new Scanner(System.in); 1

标准文档流

标准流指的是在不使用其他的与排列和定位相关的特殊CSS规则时,各种元素的排列规则.HTML文档中的元素可以分为两大类:行内元素和块级元素.       1.行内元素不占据单独的空间,依附于块级元素,行内元素没有自己的区域.它同样是DOM树中的一个节点,在这一点上行内元素和块级元素是没有区别的.       2.块级元素总是以块的形式表现出来,并且跟同级的兄弟块依次竖直排列,左右自动伸展,直到包含它的元素的边界,在水平方向不能并排.盒子在标准流中的定位原则margin控制的是盒子与盒子之间的距离,

Properties-转换流-打印流-序列化和反序列化-Commons-IO工具类

一.Properties 类(java.util)     概述:Properties 是一个双列集合;Properties 属于map的特殊的孙子类;Properties 类没有泛型,properties集合的key和value都是固定的数据类型(String),该集合提供了一些特有的方法存取值,是唯一一个可以与IO流相结合的集合; 定义:public class Properties extends Hashtable

14. 流、文件和IO

前言 InputStream/OutStream流用来处理设备之间的数据传输 Java.io 包几乎包含了所有操作输入.输出需要的类.所有这些流类代表了输入源和输出目标. Java.io 包中的流支持很多种格式,比如:基本类型.对象.本地化字符集等等. 一个流可以理解为一个数据的序列.输入流表示从一个源读取数据,输出流表示向一个目标写数据. 流按操作数据分为两种:字节流与字符流 按流向分为:输入流(InputStream)和输出流(OutputStream) Java 为 I/O 提供了强大的而