洛谷P2071 座位安排
洛谷P2071 座位安排
洛谷题目传送门
题目背景
公元二零一四年四月十七日,小明参加了省赛,在一路上,他遇到了许多问题,请你帮他解决。
题目描述
已知车上有 NNN 排座位,有 2N2N2N 个人参加省赛,每排座位只能坐两人,且每个人都有自己想坐的排数,问最多使多少人坐到自己想坐的位置。
输入格式
第一行,一个正整数 NNN。
第二行至第 2N+12N+12N+1 行,每行两个正整数 Si,1,Si,2S_{i, 1},S_{i, 2}Si,1,Si,2,为每个人想坐的排数。
输出格式
一个非负整数,为最多使得多少人满意。
输入输出样例 #1
输入 #1
4
1 2
1 3
1 2
1 3
1 3
2 4
1 3
2 3
输出 #1
7
说明/提示
对于 10%10\%10% 的数据,n≤10n \le 10n≤10;
对于 30%30\%30% 的数据,n≤50n \le 50n≤50;
对于 60%60\%60% 的数据,n≤200n \le 200n≤200;
对于 100%100\%100% 的数据,n≤2000n \le 2000n≤2000。
思路详解
确定算法
首先,我们发现这道题的意思就是有2N2N2N个人要坐NNN个椅子,每个椅子最多做两个人,每个人有他想做的椅子,求最多能让多少人做到自己想做的椅子。
根据我(题)们(目)的经(标)验(签),像这种最多可以满足多少个人的要求的显然是二分图。
明确思路
我们发现普通的二分图最大匹配中所有的点只能用一次,但是这个椅子可以给2个人坐,那怎么办呢???
考虑动用我们的神力,直接将第iii号椅子拆解为第iii号和第i+ni+ni+n号椅子,这样椅子的两边就不会相互影响了。
实现步骤
- 第iii次输入2个椅子x,yx,yx,y,建四条边(i,x),(i,y),(i,x+n),(i,y+n)(i,x),(i,y),(i,x+n),(i,y+n)(i,x),(i,y),(i,x+n),(i,y+n)
- 枚举每个人,使用匈牙利算法判断是否可行,可行则ans++ans++ans++。
- 最后直接输出答案即可。
code
#include<bits/stdc++.h>
using namespace std;
const int N=6e3+5;
int n;
vector<int>e[N];
int vis[N],fa[N];
bool dfs(int u){//匈牙利算法for(int v:e[u]){if(!vis[v]){vis[v]=1;if(!fa[v]||dfs(fa[v])){fa[v]=u;return 1;}}}return 0;
}
int main(){cin>>n;n*=2;//注意!!!n乘了2for(int i=1;i<=n;i++){int x,y;cin>>x>>y;e[i].push_back(x);e[i].push_back(x+n);//建的4条边e[i].push_back(y);e[i].push_back(y+n);}int ans=0;for(int i=1;i<=n;i++){//枚举每个imemset(vis,0,sizeof(vis));if(dfs(i))ans++;}cout<<ans;return 0;
}