2 3 0 0 0 3 0 1 1 1 1 3 4 5 0 1 0 2 3 1 2 2 0 0 1 0 2 0 4 1 3 2 0 0
4 6
题意:在一个网格里面放n个横向放的棍子,m个纵向放的棍子,每个棍子占1x2的格子。每个格子只能用一次,不能重复用。问最多能放多少个棍子。
解题:因为每个棍子只占2格,所以把所有的格子分成奇偶两部分,X , Y二部图,之间的边表示每个棍子。这样建好图之后可以用二分匹配 或 用最大流(加边<S, X , 1>, <Y , T , 1> , 每条边的最大容量为1 )。
下面是最大流解法。
#include<stdio.h>
#include<string.h>
#include<vector>
using namespace std;
const int MAXN = 10010;//点数的最大值
const int MAXM = 400010;//边数的最大值
const int INF = 0x3f3f3f3f;
struct Edge
{
int to,next,cap;
}edge[MAXM];//注意是MAXM
int tol;
int head[MAXN];
int gap[MAXN],dep[MAXN],pre[MAXN],cur[MAXN];
void init()
{
tol = 0;
memset (head,-1,sizeof(head));
}
//加边,单向图三个参数,双向图四个参数
void addEdg(int u,int v,int w,int rw=0)
{
edge[tol].to = v;edge[tol].cap = w;edge[tol].next = head[u]; head[u] = tol++;
edge[tol].to = u;edge[tol].cap = rw;edge[tol].next = head[v]; head[v]=tol++;
}
//输入参数:起点、终点、点的总数
//点的编号没有影响,只要输入点的总数
int sap(int start,int end,int N)
{
memset (gap,0,sizeof(gap));
memset (dep,0,sizeof(dep));
memcpy (cur,head,sizeof(head));
int u = start;
pre[u] = -1;
gap[0] = N;
int ans = 0;
while(dep[start] < N)
{
if(u == end)
{
for(int i = pre[u];i != -1; i = pre[edge[i^1].to])
{
edge[i].cap -= 1;
edge[i^1].cap += 1;
}
u = start;
ans += 1;
continue;
}
bool flag = false;
int v;
for(int i = cur[u]; i != -1;i = edge[i].next)
{
v = edge[i].to;
if(edge[i].cap && dep[v]+1 == dep[u])
{
flag = true;
cur[u] = pre[v] = i;
break;
}
}
if(flag)
{
u = v;
continue;
}
int Min = N;
for(int i = head[u]; i != -1;i = edge[i].next)
if(edge[i].cap && dep[edge[i].to] < Min)
{
Min = dep[edge[i].to];
cur[u] = i;
}
gap[dep[u]]--;
if(!gap[dep[u]])return ans;
dep[u] = Min+1;
gap[dep[u]]++;
if(u != start) u = edge[pre[u]^1].to;
}
return ans;
}
int main()
{
int n,m,mapt[105][105],id;
int x,y,tx,ty;
vector<int>mp[105][105];
while(scanf("%d%d",&n,&m)>0){
if(n==0&&m==0)break;
memset(mapt,0,sizeof(mapt));
for(int i=0; i<=102; i++)
for(int j=0; j<=102; j++)
mp[i][j].clear();
id=0;
while(n--){
scanf("%d%d",&x,&y);
if(mapt[x][y]==0)
mapt[x][y]=++id;
tx=x+1;
ty=y;
if(mapt[tx][ty]==0)
mapt[tx][ty]=++id;
if(((x+y)&1)==0){
mp[x][y].push_back(mapt[tx][ty]);
}
else
mp[tx][ty].push_back(mapt[x][y]);
}
while(m--){
scanf("%d%d",&x,&y);
if(mapt[x][y]==0)
mapt[x][y]=++id;
tx=x;
ty=y+1;
if(mapt[tx][ty]==0)
mapt[tx][ty]=++id;
if(((x+y)&1)==0){
mp[x][y].push_back(mapt[tx][ty]);
}
else
mp[tx][ty].push_back(mapt[x][y]);
}
init();
int s=0,t=id+1;
for(int i=0; i<=102; i++)
for(int j=0; j<=102; j++)
if(mapt[i][j]&&((i+j)&1)==0){
addEdg(s , mapt[i][j] , 1);
for(int e=0; e<mp[i][j].size(); e++){
int v=mp[i][j][e];
addEdg(mapt[i][j],v,1);
}
}
else if(mapt[i][j])
addEdg(mapt[i][j],t,1);
printf("%d\n",sap(s,t,t+1));
}
}
原文地址:http://blog.csdn.net/u010372095/article/details/46680969