[SNCPC2024] 换座位
题目描述
树王国在筹备着举办一次盛大的庆典!
Shirost 作为树王国的庆典设计师,准备邀请 \(n\) 个嘉宾来参加本次庆典。庆典上一共准备了 \(2n\) 个座位,一个座位最多只能坐一个人且一个人恰好坐一个座位。Shirost 初步计划将第 \(i\) 个嘉宾安排在第 \(i\) 个座位上。但是总统调查了这 \(n\) 个嘉宾的意愿,第 \(i\) 个嘉宾的心仪座位为第 \(a_i\) 个座位。但除非能坐到心仪座位上,否则他们只愿意坐在原来的座位上。总统希望 Shirost 能够修改计划,使得尽可能多的嘉宾坐在他们的心仪座位上。
形式化的讲,你需要找到长为 \(n\) 的数组 \(b_i\) (\(1 \leq i \leq n, 1 \leq b_i \leq 2n\)) 满足 \(\forall i \neq j,b_i \neq b_j\) 且 \(\forall i, b_i=i\) 或 \(b_i=a_i\)。且最大化 \(b_i = a_i\) 的个数。
你只需要输出最多的个数即可。
输入格式
输入第一行为一个整数 \(n\) (\(1 \leq n \leq 10^{5}\)),表示总人数。
第二行 \(n\) 个整数 \(a_i\) (\(1 \leq a_i \leq 2n\)),由空格隔开,表示每个人的心仪座位。
输出格式
输出仅一行一个整数,表示最多有多少嘉宾坐在他们的心仪座位上。
样例 #1
样例输入 #1
5
2 6 4 5 3
样例输出 #1
5
提示
所有人都可以换到自己的心仪座位。
思路
#include<bits/stdc++.h>
using namespace std;
int n,ans = 0;
int a[200010],b[200010];
vector<int> g[200010],f[200010];
int bfs(){
queue<int> q;
for(int i = 1;i <= n;i ++){
if(!b[i] && !a[i]){
q.push(i);
}
}
while(!q.empty()){
int x = q.front();
q.pop();
b[x] = 1;
for(int i = 0;i < g[x].size();i ++){
a[g[x][i]] --;
if(!a[g[x][i]]){
q.push(g[x][i]);
}
}
}
int sum = 0;
for(int i = 1;i <= n;i ++){
if(!b[i]){
sum ++;
}
}
return sum;
}
int maxx = 0;
void dfs(int x,int y){
if(x <= n){
maxx = max(maxx,y);
b[x] = 1;
}
for(int i = 0;i < f[x].size();i ++){
dfs(f[x][i],y + 1);
}
return ;
}
int dfsans(){
int sum = 0;
for(int i = n + 1;i <= n * 2;i ++){
maxx = 0;
dfs(i,0);
sum += maxx;
}
return sum;
}
int main() {
scanf("%d",&n);
for(int i = 1,aa; i <= n; i ++) {
scanf("%d",&aa);
a[aa] ++;
g[i].push_back(aa);
f[aa].push_back(i);
}
ans = dfsans() + bfs();
printf("%d\n",max(ans,0));
return 0;
}
标签:心仪,嘉宾,SNCPC2024,P10693,200010,leq,int,座位
From: https://www.cnblogs.com/zqhbxsgs/p/18365898