【每日一题】5月21日图的遍历

图的遍历

https://ac.nowcoder.com/acm/problem/52275

题意

小sun最近为了应付考试,正在复习图论,他现在学到了图的遍历,觉得太简单了,于是他想到了一个更加复杂的问题:

无向图有n个点,从点1开始遍历,但是规定:按照每次“走两步”的方式来遍历整个图。可以发现按照每次走两步的方法,不一定能够遍历整个图,所以现在小sun想问你,最少加几条边,可以完整的遍历整个图。

输入描述

第一行两个整数n,m代表图的点数和边数。

接下来m行,每行两个整数u,v代表u,v有边相连(无向边)

输出描述

输出一行,代表最少要添加的边数。

解析

要遍历所有的点肯定要所有点都相连,所以如果边数小于n-1就要先补上几条边让他们相连,好,现在我们一点一点来分析,假设所有的点在一条直线上,可以是部分点在一条直线上,

图片说明
所以很明显,如果点之间是一条直线相连,就无法做到遍历,我们再看成环,

图片说明
这里我们就可以看出来只有当点数为奇数且成环的时候我们才能做到遍历所有的点,所以如果是一条直线,那么我们将首尾相连,如果成偶数的环,我们在中间加一条线,这样就可以分割成两个奇数的环,

代码

#include <bits/stdc++.h>
using namespace std;

const int MAX = 1e5 + 7; 
int head[MAX], tot;
struct Node {
    int v, next;
} edge[MAX << 1];
int n, m, ans;
bool visited[MAX], color[MAX], flag;

void add_edge(int u, int v) {
    tot++;
    edge[tot].v = v;
    edge[tot].next = head[u];
    head[u] = tot;
}
void dfs(int u, int fa) {
    visited[u] = 1;
    for (int i = head[u]; i; i = edge[i].next) {
        int v = edge[i].v;
        if (!visited[v]) {
            color[v] = !color[u];
            dfs(v, u);
        }
        else
            if (color[v] == color[u]) flag = true;
    }
}
int main(void) { 
    cin >> n >> m;
    for (int i = 1; i <= m; i++) {
        int u, v; cin >> u >> v;
        add_edge(u, v);
        add_edge(v, u);
    }
    for (int i = 1; i <= n; i++)
        if (!visited[i]) {
            ans++;
            color[i] = true;
            dfs(i, 0);
        }
    cout << ans - 1 + !flag << endl;
    return 0; 
}
每日一题 文章被收录于专栏

写每日一题呀

全部评论

相关推荐

ProMonkey2024:5个oc?厉害! 但是有一个小问题:谁问你了?😡我的意思是,谁在意?我告诉你,根本没人问你,在我们之中0人问了你,我把所有问你的人都请来 party 了,到场人数是0个人,誰问你了?WHO ASKED?谁问汝矣?誰があなたに聞きましたか?누가 물어봤어?我爬上了珠穆朗玛峰也没找到谁问你了,我刚刚潜入了世界上最大的射电望远镜也没开到那个问你的人的盒,在找到谁问你之前我连癌症的解药都发明了出来,我开了最大距离渲染也没找到谁问你了我活在这个被辐射蹂躏了多年的破碎世界的坟墓里目睹全球核战争把人类文明毁灭也没见到谁问你了(别的帖子偷来的,现学现卖😋)
点赞 评论 收藏
分享
像好涩一样好学:这公司我也拿过 基本明确周六加班 工资还凑活 另外下次镜头往上点儿
点赞 评论 收藏
分享
11-29 11:21
门头沟学院 Java
总包48.5w,意想不到的价格
想开了的垂耳兔很喜欢拱白菜:转人工
点赞 评论 收藏
分享
评论
点赞
收藏
分享
牛客网
牛客企业服务