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

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


首先判断是否成环   如果没有环在看有几个根 也就是几个集合 (有不连通的情况)   找出所有集合中的最长链

#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
int root[100001]; 
int cut;
int head[100001];
int pre[100001];
int vis[100001];
int dist[100001];
int ans;
int n,m;
struct node 
  {
   int from,to,val,next;
   }dian[2000001];



void  Edge(int u,int v,int w)
{
	dian[cut].from =u;
	dian[cut].to =v;
	dian[cut].val =w;
	dian[cut].next =head[u];
	head[u]=cut++;
}
int jilu;
void bfs(int s)
{
memset(vis,0,sizeof(vis));
memset(dist,0,sizeof(dist));

	queue<int>q;
	q.push(s);vis[s]=1;dist[s]=0;
	while(!q.empty() )
	{
		int u=q.front() ;
		q.pop() ;
		for(int i=head[u];i!=-1;i=dian[i].next )
		{
			int v=dian[i].to ;
			if(!vis[v])
			{
				if(dist[v]<dist[u]+dian[i].val )
				dist[v]=dist[u]+dian[i].val ;
					vis[v]=1;
		            q.push(v); 	
			}
		}
     }
	 	ans=0;
	for(int i=1;i<=n;i++)
	{
			if(ans<dist[i])
		     {
			    ans=dist[i];
			    jilu=i;
	          }
	}
		
}
int find(int x)
{
  int r=x;         
  while(r!=pre[r]) 
  r=pre[r]; 
  int i=x,j;      
  while(i!=r) 
  {
   j=pre[i];pre[i]=r;i=j;
  }
 return r; 
}
int main()
{
     
	while(scanf("%d%d",&n,&m)!=EOF)
	{	
	for(int i=0;i<=n;i++)
	{
		pre[i]=i;
		}
		cut=0;
     	memset(head,-1,sizeof(head));
       	int f=0;
       	int u,v,w;
		for(int i=0;i<m;i++)
		{
			scanf("%d%d%d",&u,&v,&w);
			if(f==0)
			{
					Edge(u,v,w);
			    	Edge(v,u,w);
			}
			int dx=find(u) ;
			int dy=find(v) ;
			if(dx==dy)//判断是否成环
		    	f=1;
			 pre[dx]=dy;
		}
		if(f==1)
		{
			printf("YES
");
			continue;
		}
		int shu=0;
		for(int i=1;i<=n;i++)
		{
			if(i==pre[i])//查找一共有几个集合
			root[shu++]=i;
		}
			int max=0;
			for(int i=0;i<shu;i++)
			{
				bfs(root[i]);
			        bfs(jilu);//找出每个集合的最长链
			        if(max<ans)
			        {
			        	max=ans;
					}
			}
			printf("%d
",max);
	}
	return 0; 
}


原文地址:https://www.cnblogs.com/kingjordan/p/12027096.html