题意:n个点m条边的图,每个顶点有值d[i](0,1,-1),可以有重边或者环(无自环)
n,m<=3e5.问是否能删除某些边,使得剩下的定点i满足要么d[i]=-1或者deg[i]%2=d[i].
输出保留下来的边的编号.
首先图的度数和为偶数 若没有d[i]=-1&&d[i]之和为odd 则肯定无解
否则一定能构造:dfs生出一棵树.从叶子结点开始操作.
若当前结点d[u]==0 则说明u已经满足条件 不需要添加u-par[u]这条边.
n,m<=3e5.问是否能删除某些边,使得剩下的定点i满足要么d[i]=-1或者deg[i]%2=d[i].
输出保留下来的边的编号.
首先图的度数和为偶数 若没有d[i]=-1&&d[i]之和为odd 则肯定无解
否则一定能构造:dfs生出一棵树.从叶子结点开始操作.
若当前结点d[u]==0 则说明u已经满足条件 不需要添加u-par[u]这条边.
若当前结点d[u]==1 则需要加上u-par[u]这条边.则d[u]满足条件,改变d[par[u]]其状态,操作过程中度数和总是保持even.一定有解.
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> ii;
const int N=4e5+5;
int n,m,d[N],vis[N];
vector<ii> e[N];
vector<int> ans;
bool dfs(int u)
{
vis[u]=1;
for(int i=0;i<e[u].size();i++)
{
int v=e[u][i].first;
if(vis[v]) continue;
if(dfs(v))
{
ans.push_back(e[u][i].second);
d[v]=0;//
d[u]^=1;
}
}
return d[u];
}
int main()
{
cin>>n>>m;
int sum=0,rt=-1;
for(int i=1;i<=n;i++)
{
scanf("%d",&d[i]);
sum+=(d[i]==1);
if(d[i]==-1)
rt=i;
}
int u,v;
for(int i=1;i<=m;i++)
{
scanf("%d%d",&u,&v);
e[u].push_back(ii(v,i));
e[v].push_back(ii(u,i));
}
if(sum%2 && rt==-1)
{
puts("-1");
return 0;
}
if(sum%2) d[rt]=1;
else rt=1;
for(int i=1;i<=n;i++)
{
if(d[i]==-1)
d[i]=0;
}
dfs(rt);
cout<<ans.size()<<endl;
for(int i=0;i<ans.size();i++)
printf("%d ",ans[i]);
printf("\n");
return 0;
}