HDU 4514 设计风景线 (深林最长路)

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


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

2013腾讯编程马拉松初赛第二场(3月22日)


  并查集判断是否为森林,求森林最长路。


const int Max_N = 100008  ;
const int Max_M = 1500008 ;

bool visited[Max_N] ;
bool used[Max_N] ;
int  dist[Max_N] ;
int N , M ;

struct Edge{
       int v ;
       int w ;
       int next ;
};

Edge edge[Max_M*2] ;

int  List[Max_N] ;
int  id ;

void add_edge(int u , int v , int w){
     edge[id].v = v ;
     edge[id].w = w ;
     edge[id].next = List[u] ;
     List[u] = id++ ;
}


int father[Max_N] ;
int find_father(int x){
    if(x == father[x])
        return x ;
    else
        return father[x] = find_father(father[x]) ;
}

void bfs(int s){
     memset(dist , 0 , (N+1)*sizeof(int)) ;
     memset(visited , 0 , (N+1)*sizeof(bool)) ;
     visited[s] = 1 ;
     queue<int> que ;
     que.push(s) ;
     int u , v  , w ;
     while(! que.empty()){
          u = que.front() ;
          used[u] = 1 ;
          que.pop() ;
          for(int e = List[u] ; e != -1 ; e = edge[e].next){
              v = edge[e].v ;
              w = edge[e].w ;
              if(!visited[v]){
                   visited[v] = 1 ;
                   dist[v] = dist[u] + w ;
                   que.push(v) ;
              }
          }
     }
}

void fun(int &ans , int u){
     bfs(u) ;
     int s = max_element(dist+1 , dist+1+N) - dist ;
     bfs(s) ;
     ans = max(ans , *max_element(dist+1 , dist+1+N)) ;
}

int main(){
    int i , u , v , w , ok ;
    while(scanf("%d%d" ,&N , &M) != EOF){
         memset(List , -1 , (N+1)*sizeof(int)) ;
         id = 0 ;
         ok = 1 ;
         for(i = 1 ; i <= N ; i++)
              father[i] = i ;
         for(i = 1 ; i <= M ; i++){
              u = getint() ;
              v = getint() ;
              w = getint() ;
              if(!ok)
                 continue ;
              add_edge(u , v , w)  ;
              add_edge(v , u , w)  ;
              u = find_father(u) ;
              v = find_father(v) ;
              if(u == v){
                  ok = 0 ;
              }
              else{
                  father[u] = v ;
              }
         }
         if(!ok){
              puts("YES") ;
              continue ;
         }
         int ans = 0 ;
         memset(used , 0  , (1+N)*sizeof(bool)) ;
         for(i = 1 ; i <= N ; i++){
              if(!used[i])
                  fun(ans , i) ;
         }
         printf("%d\n" ,ans) ;
    }
    return 0 ;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值