题目背景
公元二零一四年四月十七日,小明参加了省赛,在一路上,他遇到了许多问题,请你帮他解决。
题目描述
已知车上有N排座位,有(N imes 2)个人参加省赛,每排座位只能坐两人,且每个人都有自己想坐的排数,问最多使多少人坐到自己想坐的位置。
输入格式
第一行,一个正整数(N)。
第二行至第(N imes 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\%)的数据 (Nle 10)
对于(30\%)的数据 (Nle 50)
对于(60\%)的数据 (Nle 200)
对于(100\%)的数据 (Nle 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
",ans);
}