HDU 4514 - 湫湫系列故事——设计风景线 (并查集判圈 树的直径)

随着杭州西湖的知名度提升,园林规划专家湫湫尝试设计一条环形经典观光线路,旨在利用并查集算法判断是否能形成闭环,并在未能形成环形时,探索最长可行线路长度。通过解析输入数据,湫湫巧妙地解决了路径连接问题,为游客提供了最佳游览体验。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

湫湫系列故事——设计风景线

Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)
Total Submission(s): 3029    Accepted Submission(s): 546


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

Input
  测试数据有多组,每组测试数据的第一行有两个数字n, m,其含义参见题目描述;
  接下去m行,每行3个数字u v w,分别代表这条线路的起点,终点和长度。

   [Technical Specification]
  1. n<=100000 
  2. m <= 1000000
  3. 1<= u, v <= n 
  4. w <= 1000
 

Output
  对于每组测试数据,如果能够建成环形(并不需要连接上去全部的风景点),那么输出YES,否则输出最长的长度,每组数据输出一行。
 

Sample Input
  
3 3 1 2 1 2 3 1 3 1 1
 

Sample Output
  
YES
 

Source
 

Recommend
liuyiding   |   We have carefully selected several similar problems for you:   4856  4855  4854  4853  4852 



先用并查集判断有没有环,如果没有环则求树的直径。


刚开始用dfs求树的直径 RE爆栈 然后改为bfs然后WA 

然后网上找的代码不是RE就是WA

后来用yj的一组样例才发现存在不连通的情况,然后改 结果还是WA,然后继续测试 才发现原来图G没有清空,恍然大悟 原来RE是因为没有清空G 遂改之


DFS 版 

#pragma comment(linker,"/STACK:102400000,102400000") 不用也行

#include <cstdio>
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
#include <string>
#include <map>
#include <cmath>
#include <queue>
#include <set>

using namespace std;

//#define WIN
#ifdef WIN
typedef __int64 LL;
#define iform "%I64d"
#define oform "%I64d\n"
#define oform1 "%I64d"
#else
typedef long long LL;
#define iform "%lld"
#define oform "%lld\n"
#define oform1 "%lld"
#endif

#define S64I(a) scanf(iform, &(a))
#define P64I(a) printf(oform, (a))
#define P64I1(a) printf(oform1, (a))
#define REP(i, n) for(int (i)=0; (i)<n; (i)++)
#define REP1(i, n) for(int (i)=1; (i)<=(n); (i)++)
#define FOR(i, s, t) for(int (i)=(s); (i)<=(t); (i)++)

const int INF = 0x3f3f3f3f;
const double eps = 10e-9;
const double PI = (4.0*atan(1.0));

const int maxn = 100000 + 20;
struct Node {
    int v, w;
    Node(int vv=0, int ww=0) : v(vv), w(ww) {}
};
int fa[maxn];
vector<Node> G[maxn];
int vis[maxn];
int avis[maxn];

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

bool Union(int a, int b) {
    int faa = find(a);
    int fab = find(b);
    if(faa == fab) return false;
    else fa[faa] = fab;
    return true;
}

int maxd, maxp;
void dfs(int u, int d) {
    int ret = 0;
    vis[u] = 1;
    if(d > maxd) {
        maxd = d;
        maxp = u;
    }
    for(int i=0; i<G[u].size(); i++) {
        int v = G[u][i].v;
        int w = G[u][i].w;
        if(vis[v]) continue;
        dfs(v, d+w);
    }
}

int main() {
    int n, m;

    while(scanf("%d%d", &n, &m) != EOF) {
        for(int i=1; i<=n; i++) {
            fa[i] = i;
            G[i].clear();
        }
        bool flag = false;
        for(int i=0; i<m; i++) {
            int u, v, w;
            scanf("%d%d%d", &u, &v, &w);
            if(!Union(u, v)) flag = true;
            G[u].push_back(Node(v, w));
            G[v].push_back(Node(u, w));
        }
        if(flag) {
            puts("YES");
            continue;
        }
        int ans = 0;
        memset(avis, 0, sizeof(avis));
        for(int i=1; i<=n; i++) {
            int fa = find(i);
            if(avis[fa]) continue;
            avis[fa] = 1;
            maxd = 0;
            maxp = i;
            memset(vis, 0, sizeof(vis));
            dfs(i, 0);
            memset(vis, 0, sizeof(vis));
            dfs(maxp, 0);
            ans = max(ans, maxd);
        }
        printf("%d\n", ans);
    }

    return 0;
}


BFS版

#include <cstdio>
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
#include <string>
#include <map>
#include <cmath>
#include <queue>
#include <set>

using namespace std;

//#define WIN
#ifdef WIN
typedef __int64 LL;
#define iform "%I64d"
#define oform "%I64d\n"
#define oform1 "%I64d"
#else
typedef long long LL;
#define iform "%lld"
#define oform "%lld\n"
#define oform1 "%lld"
#endif

#define S64I(a) scanf(iform, &(a))
#define P64I(a) printf(oform, (a))
#define P64I1(a) printf(oform1, (a))
#define REP(i, n) for(int (i)=0; (i)<n; (i)++)
#define REP1(i, n) for(int (i)=1; (i)<=(n); (i)++)
#define FOR(i, s, t) for(int (i)=(s); (i)<=(t); (i)++)

const int INF = 0x3f3f3f3f;
const double eps = 10e-9;
const double PI = (4.0*atan(1.0));

const int maxn = 100000 + 20;
struct Node {
    int v, w;
    Node(int vv=0, int ww=0) : v(vv), w(ww) {}
};
int fa[maxn];
vector<Node> G[maxn];
int vis[maxn];

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

bool Union(int a, int b) {
    int faa = find(a);
    int fab = find(b);
    if(faa == fab) return false;
    else fa[faa] = fab;
    return true;
}

int maxd, maxp;
queue<int> Q;
void bfs(int sn) {
    while(!Q.empty()) Q.pop();
    memset(vis, -1, sizeof(vis));
    vis[sn] = 0;
    Q.push(sn);
    while(!Q.empty()) {
        int u = Q.front();
        Q.pop();
        if(vis[u] > maxd) {
            maxd = vis[u];
            maxp = u;
        }
        int sn = G[u].size();
        for(int i=0; i<sn; i++) {
            int v = G[u][i].v;
            int w = G[u][i].w;
            if(vis[v] != -1) continue;
            vis[v] = vis[u] + w;
            Q.push(v);
        }
    }
}

int avis[maxn];

int main() {
    int n, m;

    while(scanf("%d%d", &n, &m) != EOF) {
        for(int i=1; i<=n; i++) {
            G[i].clear();
            fa[i] = i;
        }
        bool flag = false;
        for(int i=0; i<m; i++) {
            int u, v, w;
            scanf("%d%d%d", &u, &v, &w);
            if(!Union(u, v)) flag = true;
            G[u].push_back(Node(v, w));
            G[v].push_back(Node(u, w));
        }
        if(flag) {
            puts("YES");
            continue;
        }
        memset(avis, 0, sizeof(avis));
        int ans = 0;
        for(int i=1; i<=n; i++) {
            int fa = find(i);
            if(avis[fa]) continue;
            avis[fa] = 1;
            maxd = 0;
            maxp = i;
            bfs(i);
            bfs(maxp);
            ans = max(ans, maxd);
        }
        printf("%d\n", maxd);
    }

    return 0;
}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值