#include<bits/stdc++.h>
//#pragma comment(linker, "/STACK:102400000,102400000")
typedef long long ll;
//typedef pair<int,int> pii;
#define INF 1e9
#define MAXN 10005
#define MAXM 100
const int maxn = 10005;
const int mod = 1000000009;
#define eps 1e-6
#define PI 3.1415926535897932384626433
#define rep(i,n) for(int i=0;i<n;i++)
#define rep1(i,n) for(int i=1;i<=n;i++)
#define scan(n) scanf("%d",&n)
#define scan2(n,m) scanf("%d%d",&n,&m)
#define scans(s) scanf("%s",s);
#define ini(a) memset(a,0,sizeof(a))
#define FILL(a,n) fill(a,a+maxn,n)
#define out(n) printf("%d\n",n)
ll gcd(ll a,ll b) { return b==0?a:gcd(b,a%b);}
#define mk(n,m) make_pair(n,m)
using namespace std;
int dfs_clock;
int pre[maxn];
vector< pair<int,int> > G[maxn];
map< int, map<int,int> > mp; //判重
vector<int> ans;
bool iscut[maxn];
int n,m;
int dfs(int u,int fa)
{
int lowu = pre[u] = ++dfs_clock;
int child = 0;
rep(i,(int)G[u].size())
{
int v = G[u][i].first;
if(!pre[v])
{
child++;
int lowv = dfs(v,u);
lowu = min(lowu,lowv);
if(lowv >= pre[v]) iscut[u] = true; //割点
if(lowv > pre[u] && mp[u][v] == 1)
{
// iscut[u] = true;
ans.push_back(G[u][i].second); //割边
}
}
else if(v != fa)
{
lowu = min(lowu,pre[v]);
}
}
if(fa < 0 && child == 1) iscut[u] = 0;
//low[u] = lowu;
return lowu;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
// freopen("out.txt","w",stdout);
#endif
while(~scanf("%d%d",&n,&m))
{
rep1(i,n) G[i].clear();
ans.clear();
ini(pre);
ini(iscut);
mp.clear();
dfs_clock = 0;
int u,v;
rep1(i,m)
{
scan2(u,v);
G[u].push_back(mk(v,i));
G[v].push_back(mk(u,i));
//if(mp[u][v] || mp[v][u]) continue;
mp[u][v] ++; mp[v][u] ++;
}
dfs(1,-1);
sort(ans.begin(),ans.end());
cout<<ans.size()<<endl;
if(ans.size() == 0)
{
puts("");
continue;
}
rep(i,(int)ans.size())
{
printf("%d%c",ans[i],i==(int)ans.size()-1?'\n':' ');
}
}
return 0;
}
http://acdream.info/contest?cid=1131#overview
就是求割边,唯一注意点是重边肯定不是割边