题意
寻找有多少条边满足:图中所有奇环都包含这条边,且这条边不属于任何偶环
分析:
最后一个性质好坑。。。一直在想那个性质结果T3都没来得及做…
直接建一个DFS树。因为是无向图,所以只存在树边和返祖边。然后很显然只有一条返祖边与树边形成的环是有效的。
并且!返祖边有贡献当且仅当全图只有一个奇环!!!。。。。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<set>
#include<map>
#define SF scanf
#define PF printf
#define MAXN 100010
using namespace std;
void Read(int &x){
x=0;
char c;
while(c=getchar(),c!=EOF&&(c<'0'||c>'9'));
x=c-'0';
while(c=getchar(),c!=EOF&&c>='0'&&c<='9')
x=x*10+c-'0';
}
struct node{
int id,k;
int x;
bool operator <(const node &a)const {
if(k!=a.k)
return k<a.k;
return id>a.id;
}
node () {}
node (int k1,int id1,int x1):k(k1),id(id1),x(x1) {}
};
vector<node> a[MAXN];
int n,m,u,v;
int dep[MAXN],cnt1[MAXN],cnt2[MAXN];
set<int> used;
int sum;
void dfs(int x,int fa=0){
cnt1[x]=cnt2[x]=0;
for(int i=0;i<int(a[x].size());i++){
int id=a[x][i].id;
if(id==fa)
continue;
int u=a[x][i].x;
if(dep[u]==0&&u!=1){
dep[u]=dep[x]+1;
dfs(u,id);
}
else if(dep[u]>dep[x]){
if((dep[u]-dep[x])%2==0){
cnt1[u]++;
cnt1[x]--;
sum++;
}
else {
cnt2[u]++;
cnt2[x]--;
}
}
}
}
void solve(int x,int fa=0){
for(int i=0;i<int(a[x].size());i++){
int id=a[x][i].id;
if(id==fa)
continue;
int u=a[x][i].x;
if(dep[u]==0&&u!=1){
dep[u]=dep[x]+1;
a[x][i].k=1;
solve(u,id);
cnt1[x]=cnt1[x]+cnt1[u];
cnt2[x]=cnt2[x]+cnt2[u];
}
}
if(cnt2[x]==0&&cnt1[x]==sum&&fa!=0)
used.insert(fa);
}
map<pair<int,int> ,int>mp;
set<int> spe;
int main(){
freopen("voltage.in","r",stdin);
freopen("voltage.out","w",stdout);
SF("%d%d",&n,&m);
for(int i=1;i<=m;i++){
Read(u);
Read(v);
if(u>v)
swap(u,v);
if(mp.count(make_pair(u,v))){
spe.insert(mp[make_pair(u,v)]);
continue;
}
mp[make_pair(u,v)]=i;
a[u].push_back(node(0,i,v));
a[v].push_back(node(0,i,u));
}
memset(dep,0,sizeof dep);
sum=0;
dfs(1);
memset(dep,0,sizeof dep);
solve(1);
for(set<int>::iterator it=spe.begin();it!=spe.end();it++)
if(used.count(*it))
used.erase(*it);
PF("%d",used.size()+(sum==1));
}