如果原图没有奇环显然每条边都可以砍
下面讨论有奇环的情况
显然每个奇环都要砍到,所以砍的边一定在这些奇环的交中
然后有个结论,在交中砍边
1:砍的边一定不能在偶环上
2:只要不在偶环上,就是一个合法的方案
证明:
不妨设我们砍的是树边
砍掉之后,设分开的两部分为A,B,如果不考虑这些奇环的非树边,A,B分别是二分图(树是二分图
考虑这些非树边,如果这个图不是二分图,就存在奇环,一定存在一种方案,使得从A中的某个点走,经过某些非树边,最后走回A且路径长为奇数
但这种情况是不可能发生的,因为这些奇环的非树边都是连接A,B的,如果A走这些奇环的非树边,走一步后所在点层数的奇偶性不变,但因为最后要回到A,一定会在A,B之间跳跃最终走偶数条这样的边,因为路径长为奇数,于是一定走了奇数条树边,而走树边,走一步后所在点层数的奇偶性改变,走奇数条后不可能回到A,所以不会发生这种情况
这是没有偶环的时候的分析,如果砍的边在某个偶环上,这些非树边中就会存在某一条连接的两点奇偶性不同,上述的情况就会发生,即出现了一个新的奇环
命题得证
code:
#include<set>
#include<map>
#include<deque>
#include<queue>
#include<stack>
#include<cmath>
#include<ctime>
#include<bitset>
#include<string>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<climits>
#include<complex>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
inline void read(int &x)
{
char c;while(!((c=getchar())>='0'&&c<='9'));
x=c-'0';
while((c=getchar())>='0'&&c<='9') (x*=10)+=c-'0';
}
const int maxn = 1100000;
const int maxm = 1100000;
const int maxd = 22;
int n,m;
int cir,ok;
int e[maxm][2];
int v[maxm];
int fa[maxn];
int findfa(const int x){return fa[x]==x?x:fa[x]=findfa(fa[x]);}
struct edge{int y,nex,i;}a[maxn<<1]; int len,fir[maxn];
inline void ins(const int x,const int y,const int i){a[++len]=(edge){y,fir[x],i};fir[x]=len;}
int dep[maxn],fr[maxn][maxd];
void dfs(const int x)
{
for(int i=1;i<maxd;i++) fr[x][i]=fr[fr[x][i-1]][i-1];
for(int k=fir[x],y=a[k].y;k;k=a[k].nex,y=a[k].y) if(y!=fr[x][0])
{
dep[y]=dep[x]+1; fr[y][0]=x;
dfs(y);
}
}
int LCA(int x,int y)
{
if(dep[x]<dep[y]) swap(x,y);
for(int i=maxd-1;i>=0;i--) if(dep[x]-dep[y]>=(1<<i))
x=fr[x][i];
if(x==y) return x;
for(int i=maxd-1;i>=0;i--) if(fr[x][i]!=fr[y][i])
x=fr[x][i],y=fr[y][i];
return fr[x][0];
}
int flag[maxn],s[maxn];
int ans[maxm],ansn;
void solve(const int x)
{
s[x]=flag[x];
for(int k=fir[x],y=a[k].y;k;k=a[k].nex,y=a[k].y) if(y!=fr[x][0])
{
solve(y);
if(s[y]==ok) ans[++ansn]=a[k].i;
s[x]+=s[y];
}
}
int main()
{
read(n); read(m);
for(int i=1;i<=n;i++) fa[i]=i;
for(int i=1;i<=m;i++)
{
int x,y; read(x); read(y);
e[i][0]=x,e[i][1]=y;
if(findfa(x)!=findfa(y))
{
ins(x,y,i),ins(y,x,i),fa[fa[y]]=fa[x];
v[i]=1;
}
}
dep[1]=1; dfs(1);
cir=0; ok=0;
for(int i=1;i<=m;i++)
{
int x=e[i][0],y=e[i][1];
if(x==y&&cir) return puts("0"),0;
if(x==y) { cir=i; continue; }
if(!v[i])
{
int ff=LCA(x,y);
if((dep[y]-dep[ff]+dep[x]-dep[ff])&1) flag[y]--,flag[x]--,flag[ff]+=2;
else
{
v[i]=2;
ok++;
flag[x]++,flag[y]++,flag[ff]-=2;
}
}
}
if(cir)
{
if(!ok) printf("1\n%d\n",cir);
else puts("0");
return 0;
}
if(!ok)
{
printf("%d\n",m);
for(int i=1;i<m;i++) printf("%d ",i);
printf("%d\n",m);
return 0;
}
solve(1);
if(ok==1)
{
for(int i=1;i<=m;i++) if(v[i]==2)
{
ans[++ansn]=i;
break;
}
}
sort(ans+1,ans+ansn+1);
printf("%d\n",ansn);
for(int i=1;i<ansn;i++) printf("%d ",ans[i]);
if(ansn) printf("%d\n",ans[ansn]);
return 0;
}