小明在学校的编程课上了解到了关于二分图的相关知识,所谓的二分图是一种特殊的图,图中的所有顶点可以分为两个不相交的集合,而图中的所有边的两个顶点都分属于这两个集合。
换句话来说,二分图是可以进行黑白染色的图,即给图中所有顶点都涂上黑色或者白色,使得每条边的两个端点都异色。
现在小明想知道,对于任意的一个 n个顶点 m条边的无向图,通过删去一条边使其变为二分图的方案数是多少?
输入输出格式 输入格式:
第一行输入两个数 n、 m,表示图的顶点数和边数 接下来 m行,每行两个数 x、 y表示一条边(编号1~m) 输出格式:
第一行输出一个数 k,表示答案方案数 第二行输出 k个数,表示 k条边的编号,升序排列
输入样例: 9 12
1 2
1 3
2 4
2 5
3 5
4 6
4 7
5 7
6 8
7 8
7 9
8 9
可以用这个生成图
输出样例:
2
11 12
我的代码:
#include<iostream>
#include<queue>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=1000005;
int n,m;
int f[maxn];
int dis[maxn];
priority_queue<int,vector<int>,greater<int> >ans;
struct node
{
int num,c;
};
bool check[maxn];
queue<node>q;
int vis[maxn];
struct edge
{
int to,nxt;
int k;
};
edge e[maxn];
int head[maxn];
int cnt=0;
void add(int u,int v,int p)
{
cnt++;
e[cnt].to=v;
e[cnt].nxt=head[u];
e[cnt].k=p;
head[u]=cnt;
}
bool bfs()
{
// cout<<'a'<<endl;
memset(check,0,sizeof(check));
memset(vis,0,sizeof(vis));
node s;
s.c=1;
s.num=1;
vis[s.num]=1;
q.push(s);
while(!q.empty())
{
node tmp=q.front();
q.pop();
int u=tmp.num;
int f=tmp.c;
check[u]=1;
for(int i=head[u];i!=-1;i=e[i].nxt)
{
int v=e[i].to;
if(v==0)
{
continue;
}
if(vis[v]==0)
{
if(f==1)
{
vis[v]=2;
}
if(f==2)
{
vis[v]=1;
}
}
else
{
if(vis[v]==f)
{
return false;
}
}
if(check[v]==1)
{
continue;
}
node x;
x.c=vis[v];
x.num=e[i].to;
q.push(x);
}
}
return true;
}
void dfs(int u,int fa)
{
//
dis[u]=1;
for(int i=head[u];i!=-1;i=e[i].nxt)
{
if(e[i].to==fa)
{
continue;
}
if(dis[e[i].to]==2)
{
continue;
}
if(dis[e[i].to]==1)
{
int t=e[i].to;
e[i].to=0;
// cout<<fa<<" "<<u<<endl;
if(bfs())
{
//
ans.push(e[i].k);
}
e[i].to=t;
continue;
}
dfs(e[i].to,u);
}
dis[u]=2;
return;
}
int main()
{
memset(head,-1,sizeof(head));
memset(dis,0,sizeof(dis));
cin>>n>>m;
int u,v;
for(int i=1;i<=m;i++)
{
cin>>u>>v;
add(u,v,i);
add(v,u,i);
}
dfs(1,-1);
cout<<ans.size()<<'\n';
while(!ans.empty())
{
cout<<ans.top()<<' ';
ans.pop();
}
return 0;
}