洛谷P2071 座位安排
一个比较裸的二分图最大匹配。
不会的先去学习一下,P3386 【模板】二分图最大匹配。
不难发现是把每个人与希望坐的排数建一条边,但是因为一排有两个座位,所以就把每一排的两个座位拆成两个点,分别建边,再求最大匹配即可。
我把第 \(x\) 排的两个座位分别设为 \(x\) 和 \(x+i\),然后直接向这两个点建边。
#include<iostream>
#include<cstdio>
#define N 4010
#define M 16010
using namespace std;
int n;
struct edge
{
int to,nxt;
}e[M];
int head[N],tot;
void add(int x,int y) //前向星建边
{
e[++tot].to=y;
e[tot].nxt=head[x];
head[x]=tot;
}
int tim,t[N],match[N]; //tim:时间戳,后边就不用memset了,直接判断t[v]==tim
bool dfs(int x)
{
for(int i=head[x]; i; i=e[i].nxt)
{
int v=e[i].to;
if(t[v]==tim) continue;
t[v]=tim;
if(!match[v]||dfs(match[v]))
{
match[v]=x;
return true;
}
}
return false;
}
int main()
{
scanf("%d",&n);
for(int i=1; i<=n*2; i++)
{
int x,y;
scanf("%d%d",&x,&y);
add(i,x); //x排第1个座位
add(i,n+x); //x排第2个座位
add(i,y);
add(i,n+y);
}
int ans=0;
for(int i=1; i<=n*2; i++)
{
tim++; //时间戳+1
if(dfs(i)) ans++;
}
printf("%d\n",ans);
return 0;
}
$$A\ drop\ of\ tear\ blurs\ memories\ of\ the\ past.$$