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

来源:互联网 发布:ui和程序员哪个工资高 编辑:程序博客网 时间:2024/05/22 01:57

#include <iostream>
#include <cstdio>
#include <queue>
#include <cstring>
#include <cmath>
#include <vector>
#include <set>
#include <stack>
#include <algorithm>
//#include "myAlgorithm.h"

#define MAX 1000005
#define OFFENCE (1e9 + 5)
#define INF (1e8 + 5)
#define eps 1e-6
#define Rep(s, e) for( int i = s; i <= e; i++)
#define Cep(e, s) for( int i = e; i >= s; i --)
#define PI acos(-1.0)
//#pragma comment(linker, "/STACK:36777216") ///传说中的外挂
using namespace std;


///用删点法判断环, tooyang了, 后面怎么求最长路径不懂呀~, 数据太大(Bllfore-man必挂), 又是无向图~~(存在正环路, spfa搞不了)
///------------------------------实在不懂怎么弄了~~--------
///真几把水啊~~~

///如果没有环, 图已经简化为几棵树了, 如何求最长两点间的距离呢~~~
///-----------------寻求大神博客帮助

/**
    无向图的环用并查集搞定, 之前搞过的, 跪了~~~
    这样~, 无向无环图就可以看做是树

    length[find-set(v)]代表v所在的树的最所有距离,  则如果u - v存在边
    则 length[find-set(v)] += lenth[find-set(u)] + w[u, v];///

    FUNKKKKKK~~~,,,,并查集水题~ T。T
                                                原来“风景线最长长度” 是所有树的路径之和,
                                                自己YY成求距离最长的两点了间的距离了~~

*/

///------------------------------神马~~~, 题意又改成两点最长距离啦?--------------------


/**
    1.判断环: 无向图判断环, 并查集挺方便, 也好写, 一个数组, 一行代码的find_set(int);

    2.没有环的无向图, 就是n课数(n>= 1), 最长简单距离就是变成求 : 树的直径
    树的直径: 两遍最长距离, 1. 任意一点A到B, 2.B到起它点C的最长距离就是答案;
    //学习了, 树的直径还是第一次搞

    3.两遍最长距离, 可以用dfs, 但是要记忆递归答案, 可以用bfs, 但是bfs便于记录哪个点最长;

    4.对每棵树求直径, 保留最大值

    总结了前人走过的坑: 用C++交题, 加上#pragma comment(linker, "/STACK:36777216")使得栈内存开大(后面发现不用也行)
    终于猥琐的A掉了
    Accepted 1010 1890 MS 4556 KB Visual C++
*/
int n, m;
struct Ddge{
    int pos, val, next;
}ed[MAX * 2];
int head[MAX], e;
int fa[MAX];
int maxAns = 0;
void insert(int a, int b, int val){
    ed[e].next = head[a];
    ed[e].pos = b;
    ed[e].val = val;
    head[a] = e++;


    ed[e].next = head[b];
    ed[e].pos = a;
    ed[e].val = val;
    head[b] = e++;
}
int find_set(int x){
    return x == fa[x] ? x: (fa[x] = find_set(fa[x]));
}
int nodeB;
bool v[MAX];
int bfs(int nodeA){
    queue<int>q, qn;//点和步数
    q.push(nodeA);
    memset(v, 0, sizeof(int) * (n + 1));
    qn.push(0);
    v[nodeA] = 1;
    int maxLen = 0;
    while(!q.empty()){
        int node = q.front(), lent = qn.front(); q.pop(); qn.pop();
        if(maxLen < lent){///更新最大值和点
            maxLen = lent;
            nodeB = node;
        }
        int next = head[node];
        while(next != -1){
            int nodet = ed[next].pos;
            if(!v[nodet]){
                q.push(nodet);
                qn.push(lent + ed[next].val);
                v[nodet] = 1;
            }
            next = ed[next].next;
        }
    }
    return maxLen;
}
void get_max(int nodeA)
{
    bfs(nodeA);
    int maxLen = bfs(nodeB);
    maxAns = max(maxLen, maxAns);
    //cout<<maxLen<<endl;
}
int main(){
    while(cin>>n>>m){
        int u, v, val;
        bool isCycle = false;
        memset(head, -1, (n + 2) * sizeof(int));
        e = 0;
        Rep(0, n)fa[i] = i;
        Rep(1, m){
            cin>>u>>v>>val;
            if(!isCycle){
                int x = find_set(u), y = find_set(v);
                if(x != y){
                    fa[x] = y;
                    insert(u, v, val);
                }else {
                    isCycle = true;
                }
            }
        }
        if(isCycle)
            puts("YES");
        else {///计算树的直径
            maxAns = 0;
            int nodeA = find_set(1);///以代表元为第一遍的起点
            get_max(nodeA);
            Rep(2, n){
                int nodeAt = find_set(i);
                if(nodeA != nodeAt){
                    nodeA= nodeAt;
                    get_max(nodeA);
                }
            }
            cout<<maxAns<<endl;
        }
    }
    return 0;
}
/*
5 4
1 2 1
1 3 1
4 5 1
3 4 1

3 2
1 2 1
1 3 1
*/