/*
CF19E
思路:
1.先进行判断,是否所有联通分量均为二分图,如果是,那么所有边都可以
2.如不是且有>1个不是,那么无解
3.如果刚好有一个,问题可视作在一个连通且不是二分图的图上进行运算
1.回边的解:
定义在dfs树上的回边如果是构成奇环的边则成为坏边,否则是好边。
1.如果没有坏边,那么所有回边都是解(这种情况不可能因为这个图不是二分图)
2.如果有恰好一条坏边,那么这条坏边即为唯一解
3.如果有>1条坏边,那么无解
2.树边的解:
这里的奇环是指只包括一条返祖边且包括奇数条边的环,偶环同理
1.同时在所有奇环上且不在任何一个偶环上的边,使用差分进行判断即可。
*/
// 1<=n<=1e4 0<=m<=1e4 1<=v<=n 1<=u<=n
#include<bits/stdc++.h>
using namespace std;
const int MAXN=2e4+4;
int n,m,u[MAXN],v[MAXN],siz=0,siz1=1,dfn[MAXN],dep[MAXN],cha1[MAXN],cha2[MAXN],sum=0;
vector<int> e[MAXN];
int col[MAXN];
vector<int> notc,badid,ans;
bool is_two(int id,int fa){
if (col[id]==col[fa]) return 0;
if (col[id]) return 1;
col[id]=-col[fa];
for (int tmp:e[id]){
int i=v[tmp];
if (i!=fa and !is_two(i,id)) return 0;
}
return 1;
}
void dfs(int id,int in_e){
dfn[id]=++siz;
dep[id]=dep[u[in_e]]+1;
for (int tmp:e[id]){
int i=v[tmp];
if (!dfn[i]){
dfs(i,tmp);
}
else if (in_e!=(tmp^1) and dfn[id]>dfn[i]){
if ((dep[id]-dep[i])%2==0) badid.push_back(tmp),cha1[id]++,cha1[i]--,sum++;
else cha2[id]++,cha2[i]--;
}
}
}
pair<int,int> dfs1(int id,int in_e){
int sum1=cha1[id],sum2=cha2[id];
for (int tmp:e[id]){
if (in_e!=(tmp^1)) continue;
pair<int,int> an=dfs1(v[tmp],tmp);
sum1+=an.first;
sum2+=an.second;
}
if (in_e!=0)
if (sum==sum1 and !sum2)
ans.push_back(in_e/2);
return {sum1,sum2};
}
int main(){
col[0]=1;
scanf("%d %d",&n,&m);
for (int i=1;i<=m;i++){
int uu,vv;
scanf("%d %d",&uu,&vv);
u[++siz1]=uu,v[siz1]=vv;
e[uu].push_back(siz1);
u[++siz1]=vv,v[siz1]=uu;
e[vv].push_back(siz1);
}
for (int i=1;i<=n;i++){
if (!col[i])
if (!is_two(i,0))
notc.push_back(i);
}
if (notc.size()>1){ //第2点
printf("0");
return 0;
}
if (notc.empty()){ //第1点
printf("%d\n",m);
for (int i=1;i<=m;i++) printf("%d ",i);
return 0;
}
int sta=notc[0];
dfs(sta,0);
if (badid.size()==1) ans.push_back(badid[0]/2); //第3.1.2点 //第3.1.1和3.1.3被省略了
dfs1(sta,0); //第3.2.1点
sort(ans.begin(),ans.end());
printf("%d\n",ans.size());
for (int i:ans) printf("%d ",i);
return 0;
}
我的output:
0
答案:
6
312 990 1479 2729 6395 9950