大体思路是第一篇题解,我认为我连通性处理得很正确了。有注释,求调
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <vector>
#define ll long long
#define pii pair<int, int>
using namespace std;
const int N = 2e4 + 5;
int n, m, setid[N], fa[N], dep[N], diff[N], cnt, w[N];
bool ans[N], vis[N];
vector <pii> G[N];
struct Ed{
int u, v;
bool pass; //passable
}e[N];
int find(int x) {
if(x == setid[x]) return x;
return setid[x] = find(setid[x]);
}
void merge(int x, int y) {
setid[find(x)] = find(y);
return ;
}
void Spanning() { //构建一棵生成树,并且标出树边和非树边
for (int i = 1; i <= n; ++i) setid[i] = i;
for (int i = 1; i <= m; ++i) {
int u = find(e[i].u), v = find(e[i].v);
if(u != v) {
G[e[i].u].push_back(make_pair(e[i].v, i));
G[e[i].v].push_back(make_pair(e[i].u, i));
e[i].pass = 1;
setid[u] = v;
}
}
return ;
}
void dfs(int u) { //计算树上每个点的父亲节点,深度
vis[u] = 1;
for (int i = 0; i < G[u].size(); ++i) {
int v = G[u][i].first;
if(v == fa[u]) continue;
fa[v] = u, dep[v] = dep[u] + 1;
dfs(v);
}
return ;
}
void modify(int u, int v, int val) { //树上差分:将u->v路径上所有边权值+val
if(dep[v] > dep[u]) swap(u, v);
diff[u] += val, diff[v] -= val;
return ;
}
int df5(int u, int eid) { //求出边(u, fa[u]) ,即编号为eid的边的边权
vis[u] = 1;
w[eid] = diff[u];
for (int i = 0; i < G[u].size(); ++i) {
int v = G[u][i].first;
if(v == fa[u]) continue;
w[eid] += df5(v, G[u][i].second);
}
return w[eid];
}
void Extend() {
int sp = 0;
for (int i = 1; i <= m; ++i) {
if(e[i].pass) continue;
int u = e[i].u, v = e[i].v;
if(!((dep[u] + dep[v]) & 1)) {
modify(u, v, 1);
cnt++;
if(cnt == 1) sp = i;
}
else modify(u, v, -1);
}
memset(vis, 0, sizeof(vis));
for (int i = 1; i <= n; ++i) {
if(!vis[i]) df5(i, 0);
}
if(cnt == 0) {
for (int i = 1; i <= m; ++i) ans[i] = 1;
}
else {
for (int i = 1; i <= m; ++i) {
if(e[i].pass && w[i] == cnt) {
ans[i] = 1;
}
}
if(cnt == 1) ans[sp] = 1;
}
int k = 0;
for (int i = 1; i <= m; ++i) k += ans[i];
printf("%d\n", k);
for (int i = 1; i <= m; ++i) {
if(ans[i]) printf("%d ", i);
}
return ;
}
int main() {
scanf("%d %d", &n, &m);
for (int i = 1; i <= m; ++i) {
scanf("%d %d", &e[i].u, &e[i].v);
e[i].pass = 0;
}
Spanning();
for (int i = 1; i <= n; ++i) {
if(!vis[i]) dfs(i);
}
Extend();
return 0;
}