bzoj2503 相框——思路
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2503
思路题;
首先,这种问题应该注意到答案只跟度数有关,跟其他什么连接方法之类的完全无关;
关注最终状态,每个点度数都是2,所以对于原来度数不是2的需要进行处理;
也就是度数大于2的进行一次操作分成若干个2,如果是奇数那么留下一个1的等待合并,可以知道最终一定有偶数个度数为1的点;
然后考虑不是一个连通块的情况,需要把所有连通块变成链,再把它们连起来;
如果之前拆分过点,那么可以顺便多拆出两个度数为1的点,不损耗次数;
而如果原来就是一个欧拉回路,那么需要多拆一次;
然后合并,答案加上 度数为1的点数/2;
锻炼思路和码力啊!
参考TJ:https://blog.csdn.net/PoPoQQQ/article/details/48031135
代码如下:
#include<iostream> #include<cstdio> #include<cstring> using namespace std; int const maxn=150005; int n,m,deg[maxn],fa[maxn],ans,sum,cnt; bool split[maxn],odd[maxn]; int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);} int main() { scanf("%d%d",&n,&m); for(int i=1;i<maxn;i++)fa[i]=i;//maxn!! for(int i=1,x,y;i<=m;i++) { scanf("%d%d",&x,&y); // if(!x){deg[y]++; continue;} // if(!y){deg[x]++; continue;} if(!x)x=++n; if(!y)y=++n; deg[x]++; deg[y]++; fa[find(x)]=find(y); } for(int i=1;i<=n;i++) { if(deg[i]>2)ans++,split[find(i)]=1; if(deg[i]%2)sum++,odd[find(i)]=1;; if(find(i)==i&°[i])cnt++;//deg[i]! } for(int i=1;i<=n;i++) if(find(i)==i&&!odd[i]&°[i]&&cnt>1) { sum+=2; if(!split[i])ans++; } printf("%d",ans+sum/2); return 0; }
分类:
其他
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术