HDU - 4514 湫湫系列故事——设计风景线 Posted on 2018-03-15 | In 算法 , 树的直径 思路并查集判环+树的直径。注意树有可能是不连通的。树的直径通过两次bfs就能得到,具体证明见树的直径(最长路)的详细证明 代码123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293#include <bits/stdc++.h>#define ms(a,val) memset(a,val,sizeof(a))#define ll long long#define INF 0x7fffffffusing namespace std;const int MAXN=100005;const int MAXM=2000005;int n,m;int fa[MAXN],ranks[MAXN];int head[MAXN],to[MAXM],nexts[MAXM],wei[MAXM],edge,dis[MAXN];bool vis[MAXN],used[MAXN];queue<int> Q;void init(int n){ edge=0; ms(head,-1),ms(vis,0); for(int i=0;i<=n;i++)fa[i]=i,ranks[i]=0;;}int getfa(int x){ if(fa[x]==x)return x; else return fa[x]=getfa(fa[x]);}void unite(int x,int y){ x=getfa(x),y=getfa(y); if(x==y)return; if(ranks[x]<ranks[y])fa[x]=y; else{ fa[y]=x; if(ranks[x]==ranks[y])ranks[x]++; }}bool same(int x,int y){ return getfa(x)==getfa(y);}void addEdge(int u,int v,int w){ wei[edge]=w,to[edge]=v,nexts[edge]=head[u],head[u]=edge++; wei[edge]=w,to[edge]=u,nexts[edge]=head[v],head[v]=edge++;}void bfs(int s){ ms(used,0),ms(dis,0); used[s]=1,dis[s]=0; while(!Q.empty())Q.pop(); Q.push(s); while(!Q.empty()){ int u=Q.front(); Q.pop(); vis[u]=1; for(int i=head[u];~i;i=nexts[i]){ int v=to[i]; if(!used[v]){ used[v]=1; dis[v]=dis[u]+wei[i]; Q.push(v); } } }}int treedim(int s){ int u=s,maxs=0; bfs(s); for(int i=1;i<=n;i++){ if(dis[i]>maxs)u=i,maxs=dis[i]; } bfs(u); maxs=0; for(int i=1;i<=n;i++)maxs=max(maxs,dis[i]); return maxs;}int main() { int u,v,w; while(~scanf("%d%d",&n,&m)){ init(n); int flag=0; for(int i=0;i<m;i++){ scanf("%d%d%d",&u,&v,&w); if(same(u,v))flag=1; unite(u,v); addEdge(u,v,w); } if(flag)printf("YES\n"); else{ int maxs=-1; for(int i=1;i<=n;i++){ if(!vis[i])maxs=max(maxs,treedim(i)); } printf("%d\n",maxs); } } return 0;}