CodeForces - 841D Leha and another game about graph
这是一个树上差分的问题;
题目大意 给定一个不包含自环的连通图,从中选出一些边使得特定的点满足入度的奇偶性。
想一个问题,在图上,选择ab两个顶点,记录下他们的路径,经过的顶点度数+=2,对奇偶没有影响。
二两端的顶点度数++;所以问题关键,每个标记1 的点,找两个让他们添加一条边,
那么要如何操作呢,这里有一种异或的方法,
举例
list[3] = 1; list[6] = 1;
for(int i=0;i<10;i++) list[i] ^= list[i-1];
这样之后,3,4,5都被标记为1,[3,6)区间被标记成功,类似前缀和(树上差分是树的前缀和,记录边(区间));
具体看代码把
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<vector> #define maxn 300000+10 using namespace std; int list[maxn]; struct Node { int p; int len; Node(int a, int b) :p(a), len(b) {} }; vector<Node>G[maxn]; void insert(int be, int en, int len) { G[be].push_back(Node(en, len)); } vector<int>ins1, ins2,cnn; int vis[maxn]; int ans[maxn]; int dfs(int x) { vis[x] = 1; for (int i = 0; i < G[x].size(); i++) { int p = G[x][i].p; if (vis[p]) continue; dfs(p); if (ans[p]) cnn.push_back(G[x][i].len); ans[x] ^= ans[p]; } return 0; } int main() { int n, m; scanf("%d%d", &n, &m); for (int i = 1; i <= n; i++) { scanf("%d", &list[i]); if (list[i] == 1) ins1.push_back(i); if (list[i] == -1) ins2.push_back(i); } int be, en; for (int i = 1; i <= m; i++) { scanf("%d %d", &be, &en); int len = i; insert(be, en, len); insert(en, be, len); } if (ins1.size() % 2 == 1 && ins2.size() == 0) { printf("-1\n"); return 0; } for (int i = 0; i < ins1.size(); i++) { ans[ins1[i]] = 1; } if (ins1.size() % 2 == 1) ans[ins2[0]] = 1; dfs(1); printf("%d\n", cnn.size()); for (int i = 0; i < cnn.size(); i++) { printf("%d\n", cnn[i]); } return 0; }
寻找真正的热爱