HDU 4514 (无向图判断环及树的直径)

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

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

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

  • 无向图的判环:并查集,若有一组边的两个端点的根是相同的,那么就形成了环。
  • 有向图的判环:1、拓扑排序,若失败则有环 2、floyd和spfa若得到自节点的权大于0则说明有环
  • 树的直径:及树中两个节点间最长距离。求法:先从任意节点i bfs一遍,找到到i的最大距离的节点,再从这个节点出发,找到到这个节点的最大距离的,即树的直径。(结论:设树的直径是st,则从树的任意节点出发,最远点必为s或t)
#include 
#include 
#include 
#include 
#include 
#include 
#define maxn 100010
#define inf 0x3f3f3f3f3f3f
using namespace std;
int head[maxn];
int cnt=0;
int ans;
int n,m;
int s,t;
int pre[maxn];
int mark[maxn];
int dist[maxn];
int vis[maxn];
int fr(int x)
{
    if(x==pre[x])return x;
    int r=fr(pre[x]);
    return pre[x]=r;
}
bool join(int x,int y)
{
    int r1=fr(x);
    int r2=fr(y);
    if(r1==r2)return true;
    pre[r1]=r2;
    return false;
}
struct Node
{
    int fr,to,l,next;
}e[maxn*20];

void add(int a,int b,int c)
{
    e[cnt].fr=a;
    e[cnt].to=b;
    e[cnt].l=c;
    e[cnt].next=head[a];
    head[a]=cnt++;
}
void init()
{
    memset(head,-1,sizeof(head));
    cnt=0;
    ans=-1;
    memset(mark,0,sizeof(mark));
    for(int i=1;i<=n;i++)pre[i]=i;
}
void bfs(int st)
{

    memset(vis,0,sizeof(vis));
    memset(dist,0,sizeof(dist));

    queue<int>q;
    q.push(st);vis[st]=1;dist[st]=0;
    while(!q.empty() )
    {
        int u=q.front() ;
        q.pop() ;
        for(int i=head[u];i!=-1;i=e[i].next )
        {
            int v=e[i].to ;
            if(!vis[v])
            {
                if(dist[v]1;
                    q.push(v);
            }
        }
     }
        ans=0;
    for(int i=1;i<=n;i++)
    {
            if(ansint main()
{
    int a,b,c;
    int root=0;
    bool flag=false;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        init();
        flag=false;
        for(int i=0;iscanf("%d%d%d",&a,&b,&c);
            if(!flag)
            {
                add(a,b,c);
                add(b,a,c);
                if(join(a,b))flag=true;
            }
        }
        if(flag)
        {
            printf("YES\n");
        }
        else
        {
            for(int i=1;i<=n;i++)
            {
                int r=fr(i);
                if(!mark[r])
                {
                    mark[r]=1;
                    bfs(r);
                    bfs(s);
                }

            }
            printf("%d\n",ans);
        }

    }
    return 0;
}

你可能感兴趣的:(图论,搜索,并查集)