傳送門:acdream 1236
n個節點由m條邊相連,現在要毀掉一些邊,但要保證整張圖還是連通的,問哪些邊絕對不會被毀掉
這就是一個圖論找橋的問題
利用tarjan算法對於邊(u,v)如果該邊是v的父親邊,且dfn[v]==low[v]則該邊是橋
/******************************************************
* File Name: b.cpp
* Author: kojimai
* Creater Time:2014年10月07日 星期二 12時08分22秒
******************************************************/
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
#include<vector>
using namespace std;
#define FFF 10005
int first[FFF],e,dfn[FFF],low[FFF],cnt;
#define FF 100005
struct node
{
int u,v,next;
}edge[FF*2];
vector<int> ans;
void addedge(int x,int y)
{
edge[e].u = x;edge[e].v = y;edge[e].next = first[x];first[x] = e++;
edge[e].v = x;edge[e].u = y;edge[e].next = first[y];first[y] = e++;
}
int pre[FFF];
void tarjan(int x)
{
dfn[x] = low[x] = cnt++;
for(int k = first[x];~k;k = edge[k].next)
{
int v = edge[k].v;
if(dfn[v] == -1) {
pre[v] = k;
tarjan(v);
low[x] = min(low[x],low[v]);
}
else if(pre[x]/2 != k/2)
low[x] = min(low[x],dfn[v]);
}
if(pre[x]!=-1 &&low[x] == dfn[x])
ans.push_back(pre[x]/2+1);
}
int main()
{
int n,m,x,y;
memset(first,-1,sizeof(first));
e = 0;
scanf("%d%d",&n,&m);
for(int i = 0;i < m;i++)
{
scanf("%d%d",&x,&y);
addedge(x,y);
}
memset(dfn,-1,sizeof(dfn));
memset(low,0,sizeof(low));
cnt = 1;
pre[1] = -1;
tarjan(1);
//for(int i = 1;i<=n;i++)
// cout<<"dfn="<<dfn[i]<<" low="<<low[i]<<endl;
cout<<ans.size()<<endl;
for(int i = 0;i < ans.size();i++)
{
cout<<ans[i];
if(i<ans.size()-1)
cout<<' ';
else
cout<<endl;
}
return 0;
}