题意

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

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

分析

首先假设这个图是个连通图。
那么如果这个图有一个奇数大小的环,这个图的所有点一定可以被访问到。(因为可以在环上进行调整)
如果这个图不是连通图,那我们要先加边使它连通,那么原来如果有一个连通块满足全部点可以访问到,整个图一定都可以访问到。
所以我们现在就把问题转化为:求图上是否有一个奇数大小的环。
这个问题是可以用 来判断的。
最后复杂度是 的。

有个小问题

如果题目问的是图上是否有偶数大小的环,能否进行判断呢??

代码如下

#include <bits/stdc++.h>
#define N 100005
using namespace std;
typedef long long LL;
typedef unsigned long long uLL;
LL z = 1;
int read(){
    int x, f = 1;
    char ch;
    while(ch = getchar(), ch < '0' || ch > '9') if(ch == '-') f = -1;
    x = ch - '0';
    while(ch = getchar(), ch >= '0' && ch <= '9') x = x * 10 + ch - 48;
    return x * f;
}
struct node{
    int a, b, n;
}d[N * 2];
int h[N], v[N], cnt, ans, flag = 1;
void cr(int a, int b){
    d[++cnt].a = a;  d[cnt].b = b; d[cnt].n = h[a]; h[a] = cnt;
}
void dfs(int a){
    int i, b;
    for(i = h[a]; i; i = d[i].n){
        b = d[i].b;
        if(!v[b]){
            v[b] = v[a] + 1;
            dfs(b);
        }
        else if((v[a] - v[b] + 1) % 2) flag = 0;
    }
}
int main(){
    int i, j, n, m, a, b;
    n = read(); m = read();
    for(i = 1; i <= m; i++){
        a = read(); b = read();
        cr(a, b); cr(b, a);
    }
    for(i = 1; i <= n; i++) if(!v[i]) dfs(i), ans++;
    printf("%d", ans - 1 + flag);
    return 0;
}