题意:

给你n个点,m条双向边

构成一个重边无环的图

每个顶点有的值为{-1,0,1}

现在要你选择保留这个图中的某些边(可以是0条)

使得每个顶点满足以下两个条件之一

1. d[i] = -1

2.d[i] = dgree[i] % 2 (dgree[i] 为该点的度数)

请问是否有答案,无则输出-1,有则输出其中一个答案,有几条边,且是第几条边

题解:

这是一个无环的图,我们可以把它当成一颗棵树

然后从子节点开始判断,父节点与子节点的边取不取,如果叶子节点为1,那么该边一定取,取完之后,那么我们可以将节点的值进行取反,这样性质是一样的。这样一直操作,到根节点,只要根节点满足条件就一定有解,那么我们可以直接把-1的点拿来当根节点,这样就一定有解。

AC_Code:

/*
Algorithm: dfs序 
Author: anthony1314
Creat Time:
Time Complexity:
*/

#include<iostream>
#include<algorithm>
#include<queue>
#include<vector>
#include<set>
#include<stack>
#include<cstring>
#include<cstdio>
//#include<bits/stdc++.h>
#define ll long long
#define maxn 300005
#define mod 1e9 + 7
#define line printf("--------------");
using namespace std;
struct edge {
	int v, from;
} e[maxn*2];
int first[maxn], d[maxn], n, m, ans = 0, tot = 0;
bool vis[maxn], a[maxn*2];
int addedge(int u, int v) {
	tot++;
	e[tot].v = v;
	e[tot].from = first[u];
	first[u] = tot;

	tot++;
	e[tot].v = u;
	e[tot].from = first[v];
	first[v] = tot;
}

int dfs(int x){
	vis[x] = true;
	for(int i = first[x];i; i = e[i].from){
		int v = e[i].v;
		if(!vis[v]){
			if(dfs(v) & 1){
				a[i] = true;
				ans++;
				if(d[x] != 2){
					d[x] = 1 - d[x];//取反 
				}
			}
		}
	}
	return d[x]; 
}
int main() {
	scanf("%d %d", &n, &m);
	int flag = 0;
	for(int i = 1; i <= n; i++){
		scanf("%d", &d[i]);
		if(d[i] == -1){
			flag = i;
			d[i] = 2;
		}
	}
	
	int u, v;
	for(int i = 0; i < m; i++){
		scanf("%d %d", &u, &v);
		addedge(u, v);
	}
	
	if(flag){
		dfs(flag);
	}else {
		if(dfs(1) & 1){
			printf("-1\n");
			return 0;
		}
	}
	
	printf("%d\n", ans);
	for(int i = 1; i <= tot; i+=2){//因为双向边  
		if(a[i] || a[i+1]){
			printf("%d ",i/2 + 1);
		} 
	}
	return 0;
}