当前位置: 首页 > news >正文

题解:P11811 [PA 2015] 人赢 / Mistrzostwa

废话

蒟蒻的第一篇题解!

正文

(内含一组 hack,如果你只 WA 第 18 个点)。

楼上的各位大佬,讲题思路已经很详细了。

因此这篇题解主要的目的是讲几个易错点。

那就看看我的“死亡回放”吧。

错误一

30pts。

死亡原因:没读题。

我没看见有两个问号……所以只输出了集合大小。

因此我花费了一次宝贵的测试点下载机会。

下载了个样例。

那三十分纯粹就是“不可以,总司令!”。

然后就能得 30pts。

(希望这个神金的死因能让你笑一下)。

修改后代码:(非 AC!!)。

//https://www.luogu.com.cn/problem/P11811
//P11811 [PA 2015] 人赢 / Mistrzostwa
#include<iostream>
#include<queue>
#define maxn 200010
#define maxm 400010
using namespace std;
int out[maxn],vis[maxn];
struct EDGE
{int to,next;
}edge[maxm];
int tot=0,head[maxn];
void add(int u,int v)
{edge[++tot].to=v;edge[tot].next=head[u];head[u]=tot;
}
queue <int> q;
int main()
{int n,m,d;cin>>n>>m>>d;for(int i=1;i<=m;i++){int a,b;cin>>a>>b;add(a,b);add(b,a);out[a]++;out[b]++;}int ans=n;for(int i=1;i<=n;i++)if(out[i]<d){q.push(i);vis[i]=1;}while(!q.empty()){ans--;int p=q.front();q.pop();for(int i=head[p];i;i=edge[i].next){int v=edge[i].to;if(vis[v]==1)continue;out[v]--;if(out[v]<d){q.push(v);vis[v]=1;}}}if(ans==0)cout<<"NIE";else{cout<<ans<<"\n";for(int i=1;i<=n;i++)if(vis[i]==0)cout<<i<<" ";}return 0;
}
/*
4 4 2
1 2
2 3
3 4
4 23
2 3 4
*/

错误二

相信大犇们都能看出来我这个代码有大大滴问题。

所以只能得 76pts。

一个很明显的死因就是:

这张图并不一定联通。

所以我不能直接在 n 的基础上进行加减。

然后,我才想到本题的主角:并查集。

于是我就在建图的时候先连并查集。

后来对每一个集合进行类似处理。

之后得到的代码就是这个(非 AC!!!!)。

//https://www.luogu.com.cn/problem/P11811
//P11811 [PA 2015] 人赢 / Mistrzostwa
#include<iostream>
#include<queue>
#define maxn 200010
#define maxm 400010
using namespace std;
int out[maxn],vis[maxn],fa[maxn],num[maxn];
struct EDGE
{int to,next;
}edge[maxm];
int tot=0,head[maxn];
void add(int u,int v)
{edge[++tot].to=v;edge[tot].next=head[u];head[u]=tot;
}
int find(int x){return (fa[x]==x?x:fa[x]=find(fa[x]));}
void marge(int x,int y)
{x=find(x);y=find(y);if(x==y)return;fa[y]=x;
}
queue <int> q;
int main()
{int n,m,d;cin>>n>>m>>d;for(int i=1;i<=n;i++)fa[i]=i;for(int i=1;i<=m;i++){int a,b;cin>>a>>b;marge(a,b);add(a,b);add(b,a);out[a]++;out[b]++;}for(int i=1;i<=n;i++){num[find(i)]++;}for(int i=1;i<=n;i++)if(out[i]<d){q.push(i);vis[i]=1;}while(!q.empty()){int p=q.front();num[find(p)]--;q.pop();for(int i=head[p];i;i=edge[i].next){int v=edge[i].to;if(vis[v]==1)continue;out[v]--;if(out[v]<d){q.push(v);vis[v]=1;}}}int ans=0,maxnum=0;for(int i=1;i<=n;i++){if(num[i]>ans)ans=num[i],maxnum=i;}if(ans==0)return cout<<"NIE",0;cout<<ans<<"\n";for(int i=1;i<=n;i++)if(find(i)==maxnum&&vis[i]==0)cout<<i<<" ";return 0;
}
/*
4 2 1
4 1
2 32
1 4
*/

这其实是一个非常优的骗分解。

简直是我见过写过的最优的骗分解。

因为它可以骗到 97pts 的高分!!

错误三

可是您是要 AKIOI 的人!

不允许有一分的丢失!

大犇们看我代码也看出来了。

我这个代码有个非常严重的问题。

就是导出子图不一定联通。

hack

举个例子:

比如这张图 d = 3。

那么扫描一遍就会把中间的那个店删掉。

之后在扫描,就会发现所有点都“合法”。

于是程序就会把剩下并不联通的八个点一起输出了。

那通过这个,我们就能看出:

在删边前就维护集合是行不通的。

因为断边之后,集合的连通性会发生改变,而你却不自知。

又因为断边维护集合是困难的。

因此正确答案昭然若揭:

先断边,再跑并查集。

(不是这么简单的道理我咋没想到呢)

正解

正解我就不讲了。

楼上各位大犇讲得都很详细。

那我就直接扔代码了。

(AC)

Talk is cheap, show me the code.

//https://www.luogu.com.cn/problem/P11811
//P11811 [PA 2015] ÈËÓ® / Mistrzostwa
#include<iostream>
#include<queue>
#define maxn 200010
#define maxm 400010
using namespace std;
int out[maxn],vis[maxn],fa[maxn],num[maxn];
struct EDGE
{int to,next;
}edge[maxm];
int tot=0,head[maxn];
void add(int u,int v)
{edge[++tot].to=v;edge[tot].next=head[u];head[u]=tot;
}
int find(int x){return (fa[x]==x?x:fa[x]=find(fa[x]));}
void marge(int x,int y)
{x=find(x);y=find(y);if(x==y)return;fa[y]=x;
}
queue <int> q;
int main()
{int n,m,d;cin>>n>>m>>d;for(int i=1;i<=n;i++)fa[i]=i;for(int i=1;i<=m;i++){int a,b;cin>>a>>b;add(a,b);add(b,a);out[a]++;out[b]++;}for(int i=1;i<=n;i++)if(out[i]<d){q.push(i);vis[i]=1;}while(!q.empty()){int p=q.front();q.pop();for(int i=head[p];i;i=edge[i].next){int v=edge[i].to;if(vis[v]==1)continue;out[v]--;if(out[v]<d){q.push(v);vis[v]=1;}}}for(int i=1;i<=n;i++){if(vis[i]==1)continue;for(int j=head[i];j;j=edge[j].next){int t=edge[j].to;if(vis[t]==1)continue;marge(i,t);}}for(int i=1;i<=n;i++)if(vis[i]==0)num[find(i)]++;int ans=0,maxnum=0;for(int i=1;i<=n;i++){if(num[i]>ans)ans=num[i],maxnum=i;}if(ans==0)return cout<<"NIE",0;cout<<ans<<"\n";for(int i=1;i<=n;i++)if(find(i)==maxnum&&vis[i]==0)cout<<i<<" ";return 0;
}
/*
4 2 1
4 1
2 32
1 4
*/
http://www.jsqmd.com/news/63092/

相关文章:

  • 高级语言程序设计课程第八次个人作业
  • 常用adb+hdc指令
  • 详细介绍:GraphQL:让前端自己决定要什么数据
  • 2025年下半年上海ISO三体系认证机构全方位评测与选择指南
  • 2025年下半年上海ISO三体系认证服务商综合评估与选择指南
  • 2025.12.5
  • 实用指南:Configuration of TCP/IP with SSL and TLS for Database Connections
  • 20232420 2025-2026-1 《网络与系统攻防技术》实验八实验报告
  • BZOJ1278 向量 vector
  • 14.jdbc第三步PreparedStatement防sql注入
  • java
  • 详细介绍:【STL源码剖析】从源码看 heap:元素的 “下沉” 与 “上浮”
  • 大信息环境搭建从零开始(十四)CentOS 7 系统更新源更换详解:阿里云镜像源配置完整指南
  • 大信息环境搭建从零开始(十四)CentOS 7 系统更新源更换详解:阿里云镜像源配置完整指南
  • 动态规划
  • 2025年度安全狗狗驱虫药品牌排行榜:专业评测助力科学养宠
  • 2025留学生求职机构哪家强?5万offer全周期不限次服务+在职导师
  • 【Java】ArrayList
  • 实用指南:Vue编程式路由导航
  • Ubuntu 22.04 与 24.04 常用操作命令
  • 【Java】String
  • 拒绝智商税!2025最新学习机榜单发布,十大热门机型横向对比,一看就懂
  • 2025年12月留学生求职陪跑服务推荐榜:哪家更贴合专业背景定制
  • 2025年留学生求职机构排名推荐指南 途鸽求职榜首领跑赛道
  • 网络安全的守护与利器:r/netsec 月度技术讨论与工具分享
  • 重组蛋白表达纯化技术流程解析:从基因到蛋白的精准制备
  • 拒绝“中间商赚差价”!2025南京静音舱源头工厂综合实力排名发布:声博士Soundbox断层领先
  • 软件测试的分类1(含黑盒测试、白盒测试、Alpha测试、Beta测试、灰盒测试)
  • 全国中医师承选哪个机构靠谱?——在对比多家机构后最终选择了阿虎医考师承
  • 全国中医师承选哪个机构靠谱?——理性对比后选择了阿虎医考师承