显然二分图只要没有奇环就好了
于是随便搞一棵生成树然后找出所有只包含一条非树边的环就好了
……发现求的就是所有奇环的交中不被任一偶环覆盖的边
注意如果只有一个奇环的话那条非树边也是合法答案
树链求交参考NOIP2015D2T3
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define MAXN 1000005
using namespace std; int n,m;
inline int read(){
register char ch = getchar();
while(!isdigit(ch)) ch = getchar();
register int rtn = 0;
while(isdigit(ch)) rtn = rtn*10 + ch - '0' , ch = getchar();
return rtn;
}
struct t1{
int id;
int frm,to,nxt;
int cnt,tree;
}edge[MAXN<<1]; int cnt_edge = 1;
int fst[MAXN];
inline void addedge(int id,int x,int y){
edge[++cnt_edge].to = y;
edge[cnt_edge].id = id;
edge[cnt_edge].frm = x;
edge[cnt_edge].nxt = fst[x];
fst[x] = cnt_edge;
edge[++cnt_edge].to = x;
edge[cnt_edge].id = id;
edge[cnt_edge].frm = y;
edge[cnt_edge].nxt = fst[y];
fst[y] = cnt_edge;
}
int root[MAXN];
int vis[MAXN] , dex[MAXN];
int dpt[MAXN] , fth[MAXN] , edge_frm[MAXN];
int top[MAXN] , son[MAXN] , siz[MAXN] , sum[MAXN];
void dfs1(int rt,int now){
root[now] = rt;
siz[now] = 1;
vis[now] = 1;
for(int tmp =fst[now];tmp;tmp = edge[tmp].nxt){
int aim =edge[tmp].to;
if(vis[aim]) continue;
++dex[now];
edge_frm[aim] = tmp;
edge[tmp].tree = 1;
dpt[aim] = dpt[now] +1;
fth[aim] = now;
dfs1(rt,aim);
siz[now] += siz[aim];
if(siz[aim] > siz[son[now]]) son[now] = aim;
}
}
void dfs2(int now,int tp){
top[now] = tp;
if(son[now]) dfs2(son[now],tp);
for(int tmp = fst[now];tmp;tmp=edge[tmp].nxt){
if(edge[tmp].tree){
int aim = edge[tmp].to;
if(aim^son[now])
dfs2(aim,aim);
}
}
}
inline int lca(int u,int v){
while(top[u]^top[v]){
if(dpt[top[u]] < dpt[top[v]])
v = fth[top[v]];
else u =fth[top[u]];
}
return dpt[u] < dpt[v] ? u : v;
}
int cnt_odd = 0;
int rec[MAXN] , cnt_rec;
inline void make_tag(int id,int u,int v){
if(root[u]^root[v]) return ;
int LCA = lca(u,v);
int dis = dpt[u] + dpt[v] - (dpt[LCA]<<1);
if(!(dis&1)){
++cnt_odd;
++sum[u] , ++sum[v];
sum[LCA] -= 2;
rec[++cnt_rec] = id;
}
else{
--sum[u] , --sum[v];
sum[LCA] += 2;
}
}
int que[MAXN] , head,tail;
int ans = 0;
inline void push_up(){
for(int i=1;i<=n;++i) if(!dex[i]) que[tail++] = i;
int now;
while(head^tail){
now = que[head++];
if(sum[now] == cnt_odd)
++edge[edge_frm[now]].cnt , ++ans;
--dex[fth[now]];
if(!dex[fth[now]]) que[tail++] = fth[now];
sum[fth[now]] += sum[now];
}
}
int out[MAXN] , cnt_ans = 0;
int main(){
// freopen("1.in","r",stdin);
n = read() , m = read();
for(int i=1;i<=m;++i) addedge(i,read(),read());
for(int i=1;i<=n;++i){
if(!vis[i])
dfs1(i,i) , dfs2(i,i);
}
for(int i=2;i<=cnt_edge;++i)
if(edge[i].tree)
edge[i^1].tree = 1;
for(int i=2;i<=cnt_edge;++++i)
if(!edge[i].tree)
make_tag(i,edge[i].frm , edge[i].to) , edge[i].tree = edge[i^1].tree=1;
if(!cnt_odd){
printf("%d\n",m);
for(int i=1;i<=m;++i) printf("%d%c",i,i==m?'\n':' ');
return 0;
}
push_up();
if(cnt_odd==1) edge[rec[1]].cnt = 1 , ++ans;
printf("%d\n",ans);
for(int i=2;i<=cnt_edge;++i)
if(edge[i].cnt) out[++cnt_ans] = edge[i].id;
for(int i=1;i<=cnt_ans;++i) printf("%d%c",out[i],i==cnt_ans?'\n':' ');
return 0;
}