题目:
http://acm.hdu.edu.cn/showproblem.php?pid=5215
题意:
给一个无向图,无自环,无重边,问图中是否存在边数为奇数与偶数的环
思路:
二分图染色可以解决奇环,但偶环没办法直接处理
考虑到所有的环都出现在双连通子图中,用tarjan算法找出图中所有的桥,删掉
再对每个双连通子图单独染色,若在一个子图中出现了两个以上的奇环,则该图必然存在偶环
如上图,若a+b+c为一个奇环,c+d+e为另一个奇环,则a+b+d+e=(a+b+c)+(c+d+e)-c*2=奇数+奇数-偶数=偶数,必然为一个偶环
代码:
#include <stdio.h>
#include <iostream>
#include <string.h>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <algorithm>
#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std;
const int maxsize=100000+5;
struct node{
int u,father;
};
vector<int> adjList[maxsize];
int dfn[maxsize],low[maxsize];
int color[maxsize];
bool isOdd,isEven;
int sum,odd;
queue<node> q;
int index;
void tarjan(int u,int father){
dfn[u]=low[u]=++index;
for (vector<int>::iterator it=adjList[u].begin();it!=adjList[u].end();++it){
int v=*it;
if (!dfn[v]){
tarjan(v,u);
low[u]=min(low[u],low[v]);
if (dfn[u]<low[v]){
*it=0;
for (vector<int>::iterator itv=adjList[v].begin();itv!=adjList[v].end();++itv)
if (*itv == u) {*itv=0;break;}
}
}
else if (father!=v) {
low[u]=min(low[u],dfn[v]);
}
}
return;
}
void colorate(node t){
color[t.u]=1;
q.push(t);
sum++;
while (!q.empty()){
node x=q.front();
q.pop();
// cout<<"col:"<<"u color "<<x.u<<" "<<color[x.u]<<" father: "<<x.father<<" size: "<<adjList[x.u].size()<<endl;
for (vector<int>::iterator it=adjList[x.u].begin();it!=adjList[x.u].end();++it){
int v=*it;
//cout<<v<<" "<<color[v]<<endl;
if ( v==0 || v==x.father) continue;
for (vector<int>::iterator itv=adjList[v].begin();itv!=adjList[v].end();++itv)
if (*itv == x.u) {*itv=0;break;}
if (color[v]==0){
color[v]=3-color[x.u];
q.push({v,x.u});
sum++;
}
else if (color[v]==3-color[x.u]){
isEven=true;
}
else if (color[v]=color[x.u]){
isOdd=true;
odd++;
if (odd>1) isEven=true;
}
}
}
return ;
}
int main(){
int total;
cin>>total;
while (total--){
int n,m;
cin>>n>>m;
for (int i=1;i<=n;++i) adjList[i].clear();
for (int i=1;i<=m;++i){
int a,b;
scanf("%d %d",&a,&b);
adjList[a].push_back(b);
adjList[b].push_back(a);
}
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
index=0;
tarjan(1,0);
// for (int i=1;i<=n;++i){
// cout<<i<<": ";
// for (int j=0;j<adjList[i].size();++j){
// cout<<adjList[i][j]<<" ";
// }
// cout<<endl;
// }
memset(color,0,sizeof(color));
//1,2;
isOdd=false;isEven=false;
sum=0;
while (sum<n){
for (int i=1;i<=n;++i){
if (color[i]==0){
odd=0;
colorate({i,0});
}
}
}
if (isOdd) cout<<"YES"<<endl;
else cout<<"NO"<<endl;
if (isEven) cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
return 0;
}