1. 程式人生 > >Codeforces 841D Leha and another game about graph - 差分

Codeforces 841D Leha and another game about graph - 差分

新的 number == 處理 ace ood int 多余 一點

Leha plays a computer game, where is on each level is given a connected graph with n vertices and m edges. Graph can contain multiple edges, but can not contain self loops. Each vertex has an integer di, which can be equal to 0, 1 or  - 1. To pass the level, he needs to find a «good» subset of edges of the graph or say, that it doesn‘t exist. Subset is called «good», if by by leaving only edges from this subset in the original graph, we obtain the following: for every vertex i, d

i =  - 1 or it‘s degree modulo 2 is equal to di. Leha wants to pass the game as soon as possible and ask you to help him. In case of multiple correct answers, print any of them.

Input

The first line contains two integers n, m (1 ≤ n ≤ 3·105

, n - 1 ≤ m ≤ 3·105) — number of vertices and edges.

The second line contains n integers d1, d2, ..., dn ( - 1 ≤ di ≤ 1) — numbers on the vertices.

Each of the next m

lines contains two integers u and v (1 ≤ u, v ≤ n) — edges. It‘s guaranteed, that graph in the input is connected.

Output

Print  - 1 in a single line, if solution doesn‘t exist. Otherwise in the first line k — number of edges in a subset. In the next k lines indexes of edges. Edges are numerated in order as they are given in the input, starting from 1.

Examples input
1 0
1
output
-1
input
4 5
0 0 0 -1
1 2
2 3
3 4
1 4
2 4
output
0
input
2 1
1 1
1 2
output
1
1
input
3 3
0 -1 1
1 2
2 3
1 3
output
1
2
Note

In the first sample we have single vertex without edges. It‘s degree is 0 and we can not get 1.


  題目大意 給定一個不包含自環的連通圖,從中選出一些邊使得特定的點滿足入度的奇偶性。

  這裏主要的問題是要處理要求入度為奇數的點(入度為偶數的點可以不連任何邊)。然後仔細研究會發現,一條路徑除了兩端的點增加的度數為奇數,中間經過的點增加的度數都為偶數,這就很有用了。

  現在就考慮用一堆起點和終點(其實只用將要求度數為奇數的點任選兩個配對,再選剩下中的兩個,以此內推)都是要求入度為奇數的路徑把它們的邊集異或(因為當兩條路徑有一條公共的邊後就會出事情,所以需要把這條邊刪掉)後得到的新的邊集一定是合法的嗎?(當然所有選擇的點包含了所有要求入度為奇數的點)

  當要求度數為1的點的個數為奇數的時候就不一定了。因為總會存在一個點不滿足要求。那麽這時候就是沒有限制的點的表演時間,就找一條路徑把1個沒有限制的點和這個點連接起來,路上的邊的選擇情況異或一下。

  至於如何快速搞定這個一堆邊集取反的過程呢?

  首先考慮如果最終得到的圖形上出現圈是否有意義?

  答案是沒有意義,這一圈的邊全都可以去掉,因為圈 = 首位相連的路徑,這將意味著圈上任意點的度數加了2,這對奇偶性沒有影響,是多余的,可以去掉。

  所以我們選擇每條路徑的起點和終點的時候都要求它們不同,所以最終得到的圖形是森林。既然是在樹上,就可以幹很多事情了,比如樹上差分。

  然後把對 邊的取反信息 下放到子節點上(dfs樹上),接著從任意一點進行一次dfs就好了。

Code

 1 /**
 2  * Codeforces
 3  * Problem#431D
 4  * Accepted
 5  * Time: 405ms
 6  * Memory: 41000k
 7  */
 8 #include <bits/stdc++.h>
 9 using namespace std;
10 typedef bool boolean;
11 
12 int n, m;
13 int *gs;
14 int *rev;
15 vector<int> *g;
16 vector<int> *ig;
17 vector<int> c1, c2;
18 
19 inline void init() {
20     scanf("%d%d", &n, &m);
21     g = new vector<int>[n + 1];
22     ig = new vector<int>[n + 1];
23     gs = new int[(n + 1)];
24     rev = new int[(n + 1)];
25     memset(rev, 0, sizeof(int) * (n + 1));
26     for(int i = 1; i <= n; i++) {
27         scanf("%d", gs + i);
28         if(gs[i] == 1)
29             c1.push_back(i);
30         else if(gs[i] == -1)
31             c2.push_back(i);
32     }
33     for(int i = 1, u, v; i <= m; i++) {
34         scanf("%d%d", &u, &v);
35         g[u].push_back(v);
36         g[v].push_back(u);
37         ig[u].push_back(i);
38         ig[v].push_back(i);
39     }
40 }
41 
42 vector<int> res;
43 boolean *vis;
44 void dfs(int node) {
45     vis[node] = true;
46     for(int i = 0; i < (signed)g[node].size(); i++) {
47         int& e = g[node][i];
48         if(vis[e])    continue;
49         dfs(e);
50         if(rev[e])    res.push_back(ig[node][i]);
51         rev[node] ^= rev[e];
52     }
53 }
54 
55 inline void solve() {
56     int sc1 = (signed)c1.size(), sc2 = (signed)c2.size();
57     if((sc1 & 1) && !sc2) {
58         puts("-1");
59         return;
60     }
61     vis = new boolean[(n + 1)];
62     memset(vis, false, sizeof(boolean) * (n + 1));
63     for(int i = 1; i < sc1; i += 2)
64         rev[c1[i]] = rev[c1[i - 1]] = 1;
65     if(sc1 & 1)
66         rev[c1[sc1 - 1]] = rev[c2[0]] = 1;
67     dfs(1);
68     sc1 = (signed)res.size();
69     printf("%d\n", sc1);
70     for(int i = 0; i < sc1; i++)
71         printf("%d\n", res[i]);
72 }
73 
74 int main() {
75     init();
76     solve();
77     return 0;
78 }

Codeforces 841D Leha and another game about graph - 差分