HDU

题目:

随着杭州西湖的知名度的进一步提升,园林规划专家湫湫希望设计出一条新的经典观光线路,根据老板马小腾的指示,新的风景线最好能建成环形,如果没有条件建成环形,那就建的越长越好。 
现在已经勘探确定了n个位置可以用来建设,在它们之间也勘探确定了m条可以设计的路线以及他们的长度。请问是否能够建成环形的风景线?如果不能,风景线最长能够达到多少? 
其中,可以兴建的路线均是双向的,他们之间的长度均大于0。

思路:

将给出的边的两个端点用并查集放在一起,如果这两个点的祖先相等说明构成了一个环。

在这个用并查集连成的连通分量里边,找到他的root(fa[i] = i),然后先用一个BFS找到他的端点,然后从这个端点开始找树上的最长距离。

代码:

#include <bits/stdc++.h>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <vector>
#include <algorithm>
#include <queue>
#define MAX 1000000000
#define inf 0x3f3f3f3f
#define FRE() freopen("in.txt","r",stdin)

using namespace std;
typedef unsigned long long ll;
const int maxn = 100005;
int n,m;
struct Edge
{
    int to,w;
};
vector<Edge> mp[maxn];
int fa[maxn],vis[maxn],d[maxn];

int _find(int x)
{
    return fa[x] == x ? x : fa[x] = _find(fa[x]);
}

bool judgeLoop(int u,int v)
{
    int x = _find(u);
    int y = _find(v);
    if(x!=y)
    {
        fa[x] = y;
        return false;
    }
    return true;//x==y说明两者已经在一个连通分量里边了,也就是有环了
}

int BFS(int s)//两个作用1.查找最远的结点2.计算最长的距离
{
    memset(vis,0,sizeof(vis));
    memset(d,0,sizeof(d));
    vis[s] = 1;
    queue<int> que;
    que.push(s);
    int ed = s,mmax=0;
    while(!que.empty())
    {
        int u = que.front();
        que.pop();
        for(int i=0; i<mp[u].size(); i++)
        {
            Edge e = mp[u][i];
            if(vis[e.to] == 0)
            {
                d[e.to] = d[u]+e.w;//获取从根节点到e.to结点的距离
                vis[e.to] = 1;
                que.push(e.to);
                if(d[e.to]>mmax)//找到这棵树的距离根节点最远的结点
                {
                    ed = e.to;
                    mmax = d[e.to];
                }
            }
        }
    }
    return ed;
}

int main()
{
    //FRE();
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        for(int i=0; i<maxn; i++) { fa[i] = i; mp[i].clear();}
        bool ok = false;
        for(int i=0; i<m; i++)
        {
            int u,v,w;
            scanf("%d%d%d",&u,&v,&w);
            mp[u].push_back(Edge{v,w});
            mp[v].push_back(Edge{u,w});
            if(judgeLoop(u,v)) { ok = true; }
        }
        if(ok)
        {
            printf("YES
");
            continue;
        }
        int ans = 0;
        for(int i=1; i<=n; i++)
        {
            if(fa[i]==i)//找到这个树的根节点(人为设置的)
            {
                int root = BFS(i);
                int temp = BFS(root);
                ans = max(ans,d[temp]);
            }
        }
        printf("%d
",ans);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/sykline/p/10515583.html