Caterpillar POJ - 3310(树的直径)

Caterpillar POJ - 3310

An undirected graph is called a caterpillar if it is connected, has no cycles, and there is a path in the graph where every node is either on this path or a neighbor of a node on the path. This path is called the spine of the caterpillar and the spine may not be unique. You are simply going to check graphs to see if they are caterpillars.

For example, the left graph below is not a caterpillar, but the right graph is. One possible spine is
shown by dots.

这里写图片描述
Input

There will be multiple test cases. Each test case starts with a line containing n indicating the number of nodes, numbered 1 through n (a value of n = 0 indicates end-of-input). The next line will contain an integer e indicating the number of edges. Starting on the following line will be e pairs n1 n2 indicating an undirected edge between nodes n1 and n1. This information may span multiple lines. You may assume that n ≤ 100 and e ≤ 300. Do not assume that the graphs in the test cases are connected or acyclic.

Output

For each test case generate one line of output. This line should either be
    Graph g is a caterpillar.
or
    Graph g is not a caterpillar.

as appropriate, where g is the number of the graph, starting at 1.

Sample Input

22
21
1 2 2 3 2 4 2 5 2 6 6 7 6 10 10 8 9 10 10 12 11 12 12 13 12 17
18 17 15 17 15 14 16 15 17 20 20 21 20 22 20 19
16
15
1 2 2 3 5 2 4 2 2 6 6 7 6 8 6 9 9 10 10 12 10 11 10 14 10 13 13 16 13 15
0

Sample Output

Graph 1 is not a caterpillar.
Graph 2 is a caterpillar.

题意:

判断一个图是否是一棵树(是否全部连通并且不存在环),并且满足条件,存在一条链,使得所有点要么在链上要么与链上的点距离为1。
输入格式,多组输入数据,每一组,第一行个数n,第二行边数m,第三行共m对(2*m个),每一对的数字是点的编号,表示这两个点之间连一条边。

分析:

判断是否是一棵树可以用dfs。证明为什么这条链是树的直径:假设存在这样一条链,那么所有非此链上的点到此链的距离都为1,所以并不会存在一条更长的链,这条链就是最长的,即为树的直径。标记出这条链,最后判断一下所有点是否满足条件。

#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
int n,m,x,y,tot,to[1000],nxt[1000],first[200];
int dis[200],nbor[200],maxd,po,t;
bool check,flag,vis[200];

void add(int u,int v){
    to[++tot] = v;
    nxt[tot] = first[u];
    first[u] = tot;
}

void dfs1(int u,int fa){//判断是否是一棵树
    vis[u] = true;
    for(int e = first[u]; e; e = nxt[e]){
        int v = to[e];
        if(v != fa){
            if(vis[v]){//如果一个节点重复访问了,说明有环
                check = true;
                return;
            }
            dfs1(v,u);
            if(check) return;
        }
    }
}

void dfs2(int u,int fa){//寻找树的直径
    for(int e = first[u]; e; e = nxt[e]){
        int v = to[e];
        if(v != fa){
            dis[v] = dis[u] + 1;
            nbor[v] = dis[v];
            if(dis[v] > maxd){//记录最长的路径长度
                maxd = dis[v];
                po = v;
            }
            dfs2(v,u);
            nbor[u] = max(nbor[u],nbor[v]);//记录儿子所能返回的最大值,最终在直径上的点都是maxd
                                           //其他非直径上的点都小于maxd
        }
    }
}

int main(){
    while(~scanf("%d",&n) && n){
        t++;
        check = false;
        tot = 0;
        memset(vis,false,sizeof(vis));
        memset(first,0,sizeof(first));
        scanf("%d",&m);
        for(int i = 1; i <= m; i++){
            int u,v;
            scanf("%d%d",&u,&v);
            add(u,v);
            add(v,u);
        }
        if(m > n - 1) check = true;//边数多余n-1必然不是树
        if(!check) dfs1(1,0);//判断是否有环
        if(!check){
            for(int i = 1; i <= n; i++){//判断是否连通
                if(!vis[i]){
                    check = true;
                    break;
                }
            }
            if(!check){
                maxd = 0;
                memset(dis,0x3f3f3f3f,sizeof(dis));
                memset(nbor,0,sizeof(nbor));
                dis[1] = 0;
                dfs2(1,0);
                dis[po] = 0;
                dfs2(po,0);
                for(int i = 1; i <= n; i++){
                    flag = false;
                    if(nbor[i] == maxd) continue;//如果是直径上的直接跳过
                    for(int e = first[i]; e; e = nxt[e]){
                        if(nbor[to[e]] == maxd){//如果不是直径上的点必须满足存在相邻点在直径上
                            flag = true;
                            break;
                        }
                    }
                    if(!flag){
                        check = true;
                        break;
                    }
                }
            }
        }
        if(check==true) printf("Graph %d is not a caterpillar.\n",t);
        else printf("Graph %d is a caterpillar.\n",t);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/codeswarrior/article/details/82629945
今日推荐