1. 程式人生 > 其它 >圖的遍歷(深搜二分染色判斷奇環與連通 ) 歡樂賽2D

圖的遍歷(深搜二分染色判斷奇環與連通 ) 歡樂賽2D

連結:https://ac.nowcoder.com/acm/contest/16806/D
來源:牛客網

無向圖有n個點,從點1開始遍歷,但是規定:按照每次“走兩步”的方式來遍歷整個圖。可以發現按照每次走兩步的方法,不一定能夠遍歷整個圖,所以現在小sun想問你,最少加幾條邊,可以完整的遍歷整個圖。

1. 首先我們可以想到 首先得保證圖的連通性,有n個連通塊需要n-1條邊

2. 然後 需要讓(假設從1開始)其可以走到2(偶數點) 我們需要加一條邊

3 但當圖中出現奇環的時候 便可以直接走到偶數點了 所以若任一連通塊中有奇數環 則直接可以實現

判斷奇數環的方法為二分染色 如圖 深搜時隔點染色 若最後出現連線同色的情況 則有奇環

include<bits/stdc++.h>
using namespace std;
int n,m;
vector<int> g[100005];//存圖
int vis[100005];//標記是否染色,一開始為-1
int flag=1;
void dfs(int x)
{
    for(int i=0;i<g[x].size();i++)
    {
        int temp=g[x][i];
        if(vis[temp]==-1)
        {
            vis[temp]=vis[x]^1;//沒染色則染成相反的
            dfs(temp);//繼續深搜
        }
        else if(vis[temp]==vis[x])//如果發現不是二分圖說明存在奇圈
        {
            flag=0;
        }
    }
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cin>>n>>m;
    int x,y;
    for(int i=0;i<m;i++)
    {
        cin>>x>>y;
        g[x].push_back(y);
        g[y].push_back(x);
    }
    memset(vis,-1,sizeof(vis));
    int ans=0;
    for(int i=1;i<=n;i++)
    {
        if(vis[i]==-1)
        {
            ++ans;//求連通數
            vis[i]=0;//染色
            dfs(i);
        }
    }
    cout<<ans-1+flag<<endl;    
}