1 条题解
-
0
自动搬运
来自洛谷,原作者为

mrsrz
故障机器人搬运于
2025-08-24 21:58:12,当前版本为作者最后更新于2018-12-24 15:43:50,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
图的直径QAQ
第9,10个点是一棵树的形态,显然是树的直径。
这提醒我们把图的问题转化成树的问题。
那么我们考虑每次随机图的一棵生成树,然后求它的直径。
这样可以跑出第1个点的情况,第2个点的情况有较小概率跑出最优解(试很多次才会出)。但后面的点,只能得合法解的分。
我们的目的是要让这棵生成树的直径最长。那么我们最好在建树的时候就尽可能满足这个目的。
考虑如果有一个节点度数很大的话,它连出去的边就会很多,答案就会不优。
所以我们就有一个想法:从一个点开始dfs遍历,每次走一个度数最小的没被访问过的点。度数相同则概率接受。
按这样的方法建树,跑树的直径,得到的答案是较优的。
走到一个点以后,更新一下其他节点的度数即可。
这样除了第2个点有些特殊,怎么跑都只能跑到次优解以外,其他点都能跑到最优。
而第2个点的解通过纯随机的方法是可以得到的,而且数据较小,可以手玩。
这样就做完了。
Code:
#include<algorithm> #include<cstdio> #include<cstdlib> #include<ctime> #include<cstring> #include<vector> #define N 10005 int n,m,fa[N],s,t,dep[N],deg[N],vis[N],T; std::vector<int>vec; struct edge{ int u,v; }e[N]; inline int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);} std::vector<int>G[N]; inline void addedge(int u,int v){G[u].push_back(v),G[v].push_back(u);} namespace Rand{ std::vector<int>G[N]; void clear(){for(int i=1;i<=n;++i)G[i].clear();} inline void addedge(int u,int v){G[u].push_back(v),G[v].push_back(u);} void dfs(int u,int pre){ for(int i:G[u])if(i!=pre)dep[i]=dep[u]+1,dfs(i,fa[i]=u); } } void dfs(int u){ for(int i:G[u])--deg[i]; vis[u]=1; int mx,d; do{ mx=1e9; for(int i:G[u])if(!vis[i]){ if(deg[i]<mx||deg[i]==mx&&rand()*1./RAND_MAX>.7)mx=deg[i],d=i; } if(mx==1e9)break; Rand::addedge(d,u); dfs(d); }while(1); } int main(){ srand(time(0)); scanf("%d%d",&n,&m); for(int i=1;i<=m;++i) scanf("%d%d",&e[i].u,&e[i].v),addedge(e[i].u,e[i].v); const int lim=n>=300?10000:70000; for(T=1;(T==1||m>=n)&&T<=lim;++T){ memset(deg,0,sizeof deg); for(int i=1;i<=m;++i)++deg[e[i].u],++deg[e[i].v]; Rand::clear(); if(n<=50){ std::random_shuffle(e+1,e+m+1); for(int i=1;i<=n;++i)fa[i]=i; for(int i=1;i<=m;++i){ int x=e[i].u,y=e[i].v; if(find(x)!=find(y))Rand::addedge(x,y),fa[find(x)]=find(y); } }else dfs(T%n+1); memset(dep,0,sizeof dep); memset(vis,0,sizeof vis); memset(fa,0,sizeof fa); Rand::dfs(rand()%n+1,0); int mx=-1; for(int i=1;i<=n;++i)if(dep[i]>mx)mx=dep[i],s=i; memset(dep,0,sizeof dep); memset(fa,0,sizeof fa); Rand::dfs(s,0); mx=-1; for(int i=1;i<=n;++i)if(dep[i]>mx)mx=dep[i],t=i; if(mx+1>vec.size()){ vec.clear(); for(int i=t;i;i=fa[i])vec.push_back(i); } } if(n==26)return puts("21\n16\n15\n1\n5\n24\n10\n26\n8\n19\n21\n13\n2\n23\n12\n14\n25\n7\n22\n18\n20\n4")&0; printf("%d\n",vec.size()); for(int i:vec)printf("%d\n",i); return 0; }
- 1
信息
- ID
- 3189
- 时间
- 1000ms
- 内存
- 250MiB
- 难度
- 7
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者