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