判断一个图是否为树(有向图以及无向图)

整理的算法模板合集: ACM模板


判断一个图是否为树

1. 无向图(hdu 1272 小希的迷宫)

在这里插入图片描述

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<bitset>
#include<queue>
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
const int N = 200007, M = 5000007, INF = 0x3f3f3f3f;

int fa[N], n, m;
bool vis[N];

int Find(int x)
{
    if(fa[x] == x)return x;
    return fa[x] = Find(fa[x]);
}

bool unions(int x, int y)
{
    int fx = Find(x);
    int fy = Find(y);
    if(fx != fy){
        fa[fy] = fx;//注意合并的是原来的点
        return true;
    }
    return false;//有环,不是树
}

int x, y;
int kcase;

int main()
{
    while(scanf("%d%d", &x, &y)){
        kcase ++ ;
        bool flag = true;
        if(x < 0 || y < 0)
            break;
        if(x == 0 && y == 0){
            puts("Yes");
            continue;
        }
        for(int i = 0; i < N; ++ i){
            fa[i] = i;
            vis[i] = 0;
        }

        while(!(x == y && y == 0)){
            vis[x] = true;
            vis[y] = true;
            if(unions(x, y) == 0){//有环,不是树
                flag = false;
            }
            scanf("%d%d", &x, &y);
        }
        int tot = 0;
        for(int i = 1; i < N; ++ i){
            if(vis[i] && fa[i] == i)//找有几个根
                tot ++ ;
        }
        if(tot != 1)flag = false;
        //cout << tot << "ok" <<endl;
        //入度大于1了或者成树林了
        if(flag)
            printf("Yes\n");
        else
            printf("No\n");
    }
    return 0;
}

2. 有向图(hdu 1325 Is It A Tree?)

题目大意:判断一个有向图是不是一棵树

判断条件:无环,一个根节点,(只有一个入度为0的结点,不存在入度大于1的结点)

我觉得一个树应该一定有一个根节点,AC了,但是好多题解都是可以有0个根节点或者有1个根节点,也AC了…

性质:根节点入度为0,其余所有的节点入度均为1。

注意是有向图的树,所以如果一个点入度大于1就说明不是树。 而无向图就没有这个限制。

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<bitset>
#include<queue>
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
const int N = 200007, M = 5000007, INF = 0x3f3f3f3f;

int fa[N], n, m;
bool vis[N];

int Find(int x)
{
    if(fa[x] == x)return x;
    return fa[x] = Find(fa[x]);
}

bool unions(int x, int y)
{
    int fx = Find(x);
    int fy = Find(y);
    if(fx != fy){
        fa[fy] = fx;//注意合并的是原来的点
        return true;
    }
    return false;//有环,不是树
}

int x, y;
int kcase;

int main()
{
    while(scanf("%d%d", &x, &y)){
        kcase ++ ;
        bool flag = true;
        if(x < 0 || y < 0)
            break;
        if(x == 0 && y == 0){
            printf("Case %d is a tree.\n", ++ kcase);
            continue;
        }
        for(int i = 1; i < N; ++ i){
            fa[i] = i;
            vis[i] = 0;
        }

        while(!(x == y && y == 0)){
            vis[x] = true;
            vis[y] = true;
    //!因为树只有一条边指向节点,根没有边指向根节点,所以如果有两个及以上的边指向它就说明不是树
            if(Find(y) != y)
                flag = false;
            else if(unions(x, y) == 0){//有环,不是树
                flag = false;
            }
            scanf("%d%d", &x, &y);
        }
        int tot = 0;
        for(int i = 1; i < N; ++ i){
            if(vis[i] && fa[i] == i)//找有几个根
                tot ++ ;
            /*if(tot > 1){
                flag = 1;
                break;
            }*/
        }
        if(tot != 0 && tot != 1)flag = false;
        //cout << tot << "ok" <<endl;
        //入度大于1了或者成树林了
        if(flag)
            printf("Case %d is a tree.\n", kcase);
        else
            printf("Case %d is not a tree.\n", kcase);
    }
    return 0;
}


已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 撸撸猫 设计师:设计师小姐姐 返回首页