您的位置:首页 > 理论基础 > 计算机网络

Codevs_P3052 多米诺&Codevs_P1022 覆盖(二分图匹配+网络流最大流)

2016-01-05 19:08 585 查看
时间限制: 1 s

空间限制: 128000 KB

题目等级 : 大师 Master

题目描述 Description

有一个N×M的单位方格中,其中有些方格是水塘,其他方格是陆地。如果要用1×2的矩阵区覆盖(覆盖过程不容许有任何部分重叠)这个陆地,那么最多可以覆盖多少陆地面积。

输入描述 Input Description

输入文件的第一行是两个整数N,M (1<=N,M<=100),第二行为一个整数K( K<=50),接下来的K行,每行两个整数X,Y表示K个水塘的行列位置。(1<=X<=N,1<=Y<=M)。

输出描述 Output Description

输出所覆盖的最大面积块(1×2面积算一块)。

样例输入 Sample Input

4 4

6

1 1

1 4

2 2

4 1

4 2

4 4

样例输出 Sample Output

4

数据范围及提示 Data Size & Hint

见描述

思路跟方格取数3差不多,黑白染色,黑点与相邻没有被阻碍的白点连接,流量为INF,设置超级源点和超级汇点,将超级源点与黑点相连,流量为1,将白点与超级汇点相连,流量为1;

#include<cstdio>
#include<climits>
#include<cstring>
#include<vector>
#include<queue>
#include<iostream>
using namespace std;
#define N 105
#define INF INT_MAX/3*2
struct Min_Cut{
struct Edge{
int fr,to,cap,flow;
Edge(int a,int b,int c,int d):fr(a),to(b),cap(c),flow(d){}
};
vector<Edge> edge;vector<int> g[N*N];
int a[N*N],p[N*N];bool b

;
int t,n,m,k,S,T,flow;

int hash(int i,int j){return (i-1)*m+j;}
void in(int &x){
x=0;char ch=getchar();
while(ch>'9'||ch<'0') ch=getchar();
while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
}
void Add_Edge(int fr,int to,int cap,int flow){
edge.push_back(Edge(fr,to,cap,flow));
edge.push_back(Edge(to,fr,0,0));
t=edge.size();
g[fr].push_back(t-2);g[to].push_back(t-1);
}

void init(){
in(n),in(m),in(k);int x,y;S=0,T=n*m;
while(k--){
in(x),in(y);
b[x][y]=true;
}
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++){
if(((i+j)&1)&&!b[i][j]){
Add_Edge(S,hash(i,j),1,0);
if(i-1>0&&!b[i-1][j])
Add_Edge(hash(i,j),hash(i-1,j),INF,0);
if(i+1<=n&&!b[i+1][j])
Add_Edge(hash(i,j),hash(i+1,j),INF,0);
if(j-1>0&&!b[i][j-1])
Add_Edge(hash(i,j),hash(i,j-1),INF,0);
if(j+1<=m&&!b[i][j+1])
Add_Edge(hash(i,j),hash(i,j+1),INF,0);
}
if(!((i+j)&1)&&!b[i][j])
Add_Edge(hash(i,j),T,1,0);
}
}

void Max_Flow(){
for(;;){
memset(a,0,sizeof(a));a[S]=INF;int x;
queue<int> q;q.push(S);
while(!q.empty()){
x=q.front();q.pop();
for(int i=0;i<g[x].size();i++){
Edge &e=edge[g[x][i]];
if(!a[e.to]&&e.cap>e.flow){
a[e.to]=min(e.cap-e.flow,a[x]);
p[e.to]=g[x][i];
q.push(e.to);
}
}
if(a[T]) break;
}
if(!a[T]) break;
flow+=a[T];
for(x=T;x!=S;x=edge[p[x]].fr){
edge[p[x]].flow+=a[T];edge[p[x]^1].flow-=a[T];
}
}
}

void solve(){
init();Max_Flow();printf("%d\n",flow);
}

}s;
int main(){
s.solve();return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: