题解:P1543 [POI2004] SZP
思路
首先,这个题跟班花
至于求最大,贪心即可。
贪心部分
具体解释
显然的监视该人数量为
那么,对于每一个人,如果他被选了,监视他监视的人的数量就会减
如果没有人监视他监视的人了,他监视的人就不能去抱语文作业了。
正确性证明
如果我们在可以选择这个点的情况下没选这个人,那么下一个可选的点就是这个人监视的人。
按理来说,去掉这个人剩下的人少,而且去掉这个人也只有最多一个人可以被选,所以选上这个人一定是不劣的。
拓扑排序部分
显然题目没有保证是一个 DAG,而且样例也足够让我们看出它是有环的。
不过既然是环,那么从随便一个点断开都是等价的,所以就可以直接找一个环上的点断环就行了。
#include<bits/stdc++.h>
using namespace std;
struct node{
int u,v,nxt;
}e[1000005];
int n,x[1000005];
queue<int>q;
int vis[1000005],ru[1000005],chu[1000005],ans[1000005],sum;
void bfs(){
while(!q.empty()){
int u=q.front();q.pop();
vis[u]=1;
if(ans[u]){
ru[x[u]]--;
if(ru[x[u]]==0)q.push(x[u]);
}
else{
if(!ans[x[u]]){
ans[x[u]]=1;
sum++;
q.push(x[u]);
}
}
}
}
int main(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>x[i];
ru[x[i]]++;
chu[i]++;
}
for(int i=1;i<=n;i++){
if(ru[i]==0)q.push(i);
}
bfs();
for(int i=1;i<=n;i++){
if(!vis[i]){
vis[i]=1;
int j=i;
while(!vis[x[j]]){
if(!ans[x[j]]&&!ans[j]){
ans[x[j]]=1;
sum++;
}
j=x[j];
vis[j]=1;
}
}
}
cout<<sum;
return 0;
}
时间复杂度
分类:
题解
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】