Codeforces 454E. Little Pony and Summer Sun Celebration

题意:给n个点m条边的无向图,并给出每个点的访问次数奇偶,求构造一条满足条件的路径(点和边都可以走)。

解法:这道题还蛮有意思的。首先我们可以发现在一棵树上每个儿子的访问次数的奇偶是可以被它的父亲控制的,因为可以x->fa->x这样的话x和父亲的访问次数都+1了,同样道理x的父亲的访问次数奇偶也可以被其父亲的父亲控制。由此可得,只有根节点不能被别人控制,但是因为回溯的缘故,我们可以通过控制最后回溯到根节点的这一步走不走来控制根节点的奇偶。这道题就解了。

这里有一个细节:因为图不一定连通,不能只把1作为起点,应该随便找一个奇数点作为起点。

细节详见代码:

#pragma comment(linker,"/STACK:102400000,102400000")
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
int n,m,rt,Size,cnt[N],jo[N];
vector<int> ans,G[N];
bool vis[N];

void dfs(int x,int fa) {
    vis[x]=rt;
    ans.push_back(x); cnt[x]++;
    for (int i=0;i<G[x].size();i++) {
        int y=G[x][i];
        if (vis[y]) continue;
        dfs(y,x);
        ans.push_back(x); cnt[x]++;
    }
    if (x!=rt)
        if (cnt[x]%2!=jo[x]) {
            ans.push_back(fa); cnt[fa]++;
            ans.push_back(x); cnt[x]++;
        }
}

int main()
{
    cin>>n>>m;
    for (int i=1;i<=m;i++) {
        int x,y; scanf("%d%d",&x,&y);
        G[x].push_back(y);
        G[y].push_back(x);
    }
    for (int i=1;i<=n;i++) scanf("%d",&jo[i]);
    
    rt=1; for (int i=1;i<=n;i++) if (jo[i]) rt=i; 
    dfs(rt,0);
    
    int Size=ans.size();
    if (cnt[rt]%2!=jo[rt]) cnt[rt]--,Size--;
    for (int i=1;i<=n;i++)
        if (cnt[i]%2!=jo[i]) { puts("-1"); return 0; }
    cout<<Size<<endl;
    for (int i=0;i<Size;i++) printf("%d ",ans[i]);
    return 0;
} 
原文地址:https://www.cnblogs.com/clno1/p/10845555.html