Codeforces841D dfs+脑洞

来源:互联网 发布:网络整合营销的道与术 编辑:程序博客网 时间:2024/06/03 21:42

题目链接:http://codeforces.com/contest/841/problem/D


题意:给你一个n个点m条边的联通无向图,有重边无自环,每个点有一个权值d,d[i]={-1,0,1},要求在图中选择一些边使得对于图中的任意点 i 有度数x%2==d[i]或者d[i]==-1.


思路:考虑一条边都不选的时候,那么d[i]==1的点将不满足要求,我们就必须要给它加一条边。如果我们用dfs来维护这个过程,对于d[i]>=0的点,添边的过程实际上是d[i]取反的过程,我们从叶子结点向上搜索,对于每一棵子树u(u为父节点),如果u的子节点v d[v]==1,我们就在u和v之间连一条边,表现为d[u](d[u]!=-1)和d[v]取反,由于对一个节点进行取反并不影响他的子节点的状态,所以当我们将这个过程进行完毕后只有根节点的状态是不确定的,那么对于根节点u,如果d[u]==0或者d[u]==-1,那么此时选取的边已经符合要求,如果d[u]==1,考虑如果它的所有子节点中,存在一点x d[x]==-1,那么我们遍历从x到u的路径,并沿途取反,此时这条路径上只有u的状态会发生改变,其他的状态均不会发生改变,此时d[u]==0,符合题意要求,输出即可。因此输出-1的条件就是不存在一个点i d[i]==-1(题目保证图联通)


参考题解传送门:点击打开链接


代码:


#include <iostream>#include <string.h>#include <stdlib.h>#include <stdio.h>#include <algorithm>#include <cstdio>#include <time.h>#include <queue>#include <set>#include <map>#include <stack>#include <math.h>//#include <bits/stdc++.h>#define ll long long#define int64 long long#define mem(x,y) memset(x,y,sizeof(x))#define ull unsigned long long#define pb push_back#define INF 0x3f3f3f3f#define lson l, mid, rt<<1#define rson mid+1, r, rt<<1|1#define pi 3.141592653589793238462#define stdio std::ios::sync_with_stdio(false)using namespace std;inline bool nextDouble(double &num) {    char in;    double Dec = 0.1;    bool IsN = false, IsD = false;    in = getchar();    if (in == EOF) return false;    while (in != '-' && in != '.' && (in < '0' || in > '9'))        in = getchar();    if (in == '-') {        IsN = true;        num = 0;    } else if (in == '.') {        IsD = true;        num = 0;    } else num = in - '0';    if (!IsD) {        while (in = getchar(), in >= '0' && in <= '9') {            num *= 10;            num += in - '0';        }    }    if (in != '.') {        if (IsN) num = -num;        return true;    } else {        while (in = getchar(), in >= '0' && in <= '9') {            num += Dec * (in - '0');            Dec *= 0.1;        }    }    if (IsN) num = -num;    return true;}inline bool nextInt(int &num) {    char in;    bool IsN = false;    in = getchar();    if (in == EOF) return false;    while (in != '-' && (in < '0' || in > '9')) in = getchar();    if (in == '-') {        IsN = true;        num = 0;    } else num = in - '0';    while (in = getchar(), in >= '0' && in <= '9') {        num *= 10, num += in - '0';    }    if (IsN) num = -num;    return true;}inline bool nextLong(ll &num) {    char in;    bool IsN = false;    in = getchar();    if (in == EOF) return false;    while (in != '-' && (in < '0' || in > '9')) in = getchar();    if (in == '-') {        IsN = true;        num = 0;    } else num = in - '0';    while (in = getchar(), in >= '0' && in <= '9') {        num *= 10, num += in - '0';    }    if (IsN) num = -num;    return true;}const int maxn = 3e5 + 5;const int maxm = 1e3 + 5;const int mod = 1e9 + 7;const int seed = 10007;const double eps = 1e-6;int n, m;typedef pair<int, int> P;int d[maxn];vector<P> g[maxn];bool vis[maxn], select[maxn];P fa[maxn];void dfs(int u) {    for (int i = 0; i < (int)g[u].size(); i++) {        int v = g[u][i].first;        int id = g[u][i].second;        if (vis[v]) continue;        vis[v] = 1;        fa[v] = P(u, id);        dfs(v);        if (d[v] == 1) {            d[v] = 0;            select[id] ^= 1;            if (d[u] != -1) d[u] ^= 1;        }    }}int main() {    stdio;    cin >> n >> m;    int flag = -1;    for (int i = 1; i <= n; i++) {        cin >> d[i];        if (d[i] == -1) flag = i;    }    int a, b;    for (int i = 1; i <= m; i++) {        cin >> a >> b;        g[a].pb(P(b, i));        g[b].pb(P(a, i));    }    mem(vis, 0);    mem(select, 0);    vis[1] = 1;    dfs(1);    if (d[1] == 1) {        if (flag == -1) {            cout << -1 << endl;            return 0;        } else {            while (flag != 1) {                select[fa[flag].second] ^= 1;                flag = fa[flag].first;            }        }    }    int ans = 0;    for (int i = 1; i <= m; i++) {        if (select[i]) ans++;    }    cout << ans << endl;    for (int i = 1; i <= m; i++) {        if (select[i]) cout << i << " ";    }    cout << endl;    return 0;}


原创粉丝点击