题目链接:http://codeforces.com/contest/962/problem/F
点双,把每个边属于拿个联通分量搞出来,然后判断每个联通分量里的点和边的数目是否相等,如果相等则所有边都属于一个简单环,直接上Tarjan点双的板子就行了,主义割点可以属于多个联通分量
代码:
#include<bits/stdc++.h>
using namespace std;
const int MAXN=1e5+5;//点数
const int MAXM=2e5+5;//边数,因为是无向图,所以这个值要*2
struct node
{
int next,to,id;
}edge[MAXM];
bool Instack[MAXN],cut[MAXN],vis[MAXM];
int head[MAXN],DFN[MAXN],Low[MAXN],Belong[MAXM],Stack[MAXM];
int tot,Index,root,top,block;
void addedge(int u,int v,int id)
{
edge[tot].to=v;edge[tot].id=id;edge[tot].next=head[u];
head[u]=tot++;
}
void Tarjan(int u,int fa)//fa初值一定要为-1
{
int cnt=0;
DFN[u]=Low[u]=++Index;
Instack[u]=1;
for(int i=head[u];~i;i=edge[i].next)
{
int v=edge[i].to;
if(vis[edge[i].id]) continue;
vis[edge[i].id]=true;
Stack[++top]=edge[i].id;
if(DFN[v]==-1)
{
Tarjan(v,u);
cnt++;
if(Low[u]>Low[v]) Low[u]=Low[v];
if(fa<0&&cnt>1) cut[u]=1;
else if(fa>=0&&Low[v]>=DFN[u]) cut[u]=1;
if(Low[v]>=DFN[u])
{
int t;
block++;
do
{
t=Stack[top--];
Belong[t]=block;
}while(t!=edge[i].id);
}
}
else if(Instack[v]&&Low[u]>DFN[v])
Low[u]=DFN[v];
}
}
void init()
{
memset(DFN,-1,sizeof(DFN));
memset(Low,0,sizeof(Low));
memset(Instack,0,sizeof(Instack));
memset(cut,0,sizeof(cut));
memset(head,-1,sizeof(head));
memset(vis,false,sizeof(vis));
tot=0;Index=0;top=0;block=0;
}
bool ans[MAXM],bk[MAXM],ou[MAXM];
int cntp[MAXM],cnte[MAXM];
void solve(int n,int m)
{
for(int i=1;i<=n;i++)
if(DFN[i]==-1)
Tarjan(i,-1);
memset(cntp,0,sizeof(cntp));
memset(cnte,0,sizeof(cnte));
memset(bk,false,sizeof(bk));
for(int i=1;i<=n;i++)
{
for(int j=head[i];~j;j=edge[j].next)
{
int id=edge[j].id;
id=Belong[id];
cnte[id]++;
if(!bk[id])
{
bk[id]=true;
cntp[id]++;
}
}
for(int j=head[i];~j;j=edge[j].next)
{
int id=edge[j].id;
id=Belong[id];
bk[id]=false;
}
}
for(int i=1;i<=block;i++)
{
cnte[i]/=2;
if(cnte[i]==cntp[i]) ans[i]=true;
}
for(int i=1;i<=n;i++)
for(int j=head[i];~j;j=edge[j].next)
{
int id=edge[j].id;
id=Belong[id];
if(ans[id])
ou[edge[j].id]=true;
}
int tot=0;
for(int i=1;i<=m;i++)
{
if(ou[i]) tot++;
}
printf("%d\n",tot);
for(int i=1;i<=m;i++)
{
if(ou[i]) printf("%d ",i);
}
puts("");
}
int main()
{
//freopen("in.txt","r",stdin);
int n,m;
int u,v;
while(~scanf("%d%d",&n,&m))
{
init();
for(int i=1;i<=m;i++)
{
scanf("%d%d",&u,&v);
addedge(u,v,i);
addedge(v,u,i);
}
solve(n,m);
}
return 0;
}