P2071 【座位安排】【二分图】
题目背景
公元二零一四年四月十七日,小明参加了省赛,在一路上,他遇到了许多问题,请你帮他解决。
题目描述
已知车上有N排座位,有\(N\times 2\)个人参加省赛,每排座位只能坐两人,且每个人都有自己想坐的排数,问最多使多少人坐到自己想坐的位置。
输入格式
第一行,一个正整数\(N\)。
第二行至第\(N\times 2+1\)行,每行两个正整数\(S_{i1},S_{i2}\),为每个人想坐的排数。
输出格式
一个非负整数,为最多使得多少人满意。
输入输出样例
输入 #1
4
1 2
1 3
1 2
1 3
1 3
2 4
1 3
2 3
输出 #1
7
说明/提示
对于\(10\%\)的数据 \(N\le 10\)
对于\(30\%\)的数据 \(N\le 50\)
对于\(60\%\)的数据 \(N\le 200\)
对于\(100\%\)的数据 \(N\le 2000\)
分析
一道二分图的基础板子题。
首先每个人都有自己想坐的两排,如果每排只有一个人,那么我们直接建边求出来最大匹配就可以了,但是这个题与众不同的是每一排能够坐下两个人,那么我们在建边的时候就不能单纯的建从人到排数的边了。
每个人都有两个希望坐的排,并且每一排都可以坐下两个人,所以我们在建边的时候再向\(n+x\)和\(n+y\)建一条边,其中\(x\)和\(y\)都是当前这个人想要坐的排数。
建好边以后就可以直接跑匈牙利了,最后统计答案。
这里我用的是\(vector\)存图,比较好看。
代码
#include<bits/stdc++.h>
using namespace std;
const int maxn = 2e4+10;
int n;
int ans;
int match[maxn<<1];
int vis[maxn<<1];
vector<int>g[maxn<<1];
int dfs(int x){//匈牙利算法
int siz = g[x].size();
for(int i=0;i<siz;++i){
int v=g[x][i];
if(!vis[v]){
vis[v] = 1;
if(!match[v] || dfs(match[v])){
match[v] = x;
return 1;
}
}
}
return 0;
}
int main(){
scanf("%d",&n);
for(int i=1;i<=2*n;++i){
int x,y;
scanf("%d%d",&x,&y);//建边
g[i].push_back(x);
g[i].push_back(y);
g[i].push_back(x+n);
g[i].push_back(y+n);
}
for(int i=1;i<=2*n;++i){//匈牙利
memset(vis,0,sizeof(vis));
ans+=dfs(i);
}
printf("%d\n",ans);
}
$Never\ Give\ Up$