题意:
一次走两步 问最少添加几条边 可以完整的遍历整张图
思路:
考虑环的奇偶性。
如果有奇环,那么从奇环的任意点出发,一定能够走完这个环。
所以如果存在某个连通块是奇环,那么就只需要把剩下的连通块都连接到该连通块上即可,所需要的添加边数就是连通块数-1;
如果不存在奇环的话,先要将某个连通块变成奇环,增加一条边即可,然后再按照上述思路,所需要添加的边数就是连通块数-1+1,即连通块数。
当存在某个连通块是奇环时,我们来考虑剩下的连通块。其中如果有连通块是奇环的话,可以不予考虑,因为一定可以走完。只考虑连通块是偶环(不知道有没有这个词emm)的个数cnt。无论cnt是奇数还是偶数,偶数相加一定是偶数,所以再加上之前的奇环的连通块,就一定是奇数,所以是相当于构成了一个奇环,是可以走完的。
判断奇环染色的原理就类似于二分图染色,dfs即可。具体的就看一下代码叭。
#include<bits/stdc++.h> using namespace std; const int maxn=2e5+100; vector<int>e[maxn]; int col[maxn]; bool flag=0;//是否存在奇环 void dfs(int color,int u){ col[u]=color; for(auto it:e[u]){ if(!col[it]) dfs(3-color,it); else if(col[u]==col[it]) flag=1; } } int main(){ int n,m; cin>>n>>m; for(int i=1;i<=m;i++){ int u,v; cin>>u>>v; ///无向图 e[u].push_back(v); e[v].push_back(u); } int res=0; for(int i=1;i<=n;i++) if(!col[i]) dfs(1,i),res++; if(flag) cout<<res-1<<endl; else cout<<res<<endl; return 0; }