如果要遍历全图,第一个条件就是要确保全图是连通的,所以第一步确定连通块的数量,假设连通块的数量是n,那么如果一个图中存在奇数环,如 (1,2)(2,3)(3,1)那么奇数环就可以遍历全图,而此时需要的边的数量就是n-1,剩下所有的连通块全部连接到奇数环上,比如一个偶数环,无论从那个点出发都无法遍历全图,总会剩下一半的点遍历不到,而连接到奇数环上,就可以,比如第一次进入偶数环的点是x点,那么在奇数环中转一圈进入的就是与x点相连的点,然后可以遍历全图,然后如果一个图中没有奇数环,那么需要构造一个奇数环,也就是偶数环或者不成环的连通块加1条边即可构成奇数环,那么次数需要的边数为n
时间复杂度:
#include<bits/stdc++.h> using namespace std; vector<int> tu[300000]; int ans; int flag[300000]; int flag2[300000]; int flag4; void dfs(int x,int y,int z) { flag[x]=1; flag2[x]=z; z=3-z; for(int i=0; i<tu[x].size(); i++) { int j=tu[x][i]; if(!flag[j]) dfs(j,y,z); else if(flag2[x]==flag2[j]) flag4=1; } } int main() { int n,m; cin>>n>>m; for(int i=0; i<m; i++) { int a,b; cin>>a>>b; tu[a].push_back(b); tu[b].push_back(a); } for(int i=1; i<=n; i++) { if(!flag[i]) { ans++; dfs(i,i,1); } } cout<<ans-flag4; }
写的代码比较垃圾.........又长跑的又慢..........仅供参考