CF 453C. Little Pony and Summer Sun Celebration

构造题。

题目大意,给定一个无向图,每个点必须被指定的奇数或者偶数次,求一条满足条件的路径(长度不超\(4n\)).没有输出-1

首先我们应该判断掉-1的情况

图不连通且所有的奇数点不在同一个联通块内

发现只有上述情况可以

为什么

我们发现图不连通但所有的奇数点在同一个联通块内和图连通在本质上是一种情况.

我们在这里就只考虑图连通该怎么办.

首先,我们对于这张图求出他任意一个生成树
之后我们进行dfs,在dfs再次回到\(x\)点时(即我们已经处理玩了\(x\)的所有子树),我们就要求他合法.但是,万一他不合法怎么办?

很简单,我们就利用他的父亲.即\(x->f->x\)这样的话,虽然改变了\(f\),但是我们完成了将\(x\)的子树全部合法的任务

其他的所有点都以此类推

但是,万一我们求完整棵树,发现根不合法怎么办?

不慌,我们先随便找到\(root\)的一个儿子,记为\(s\)

那么直接\(root->s-root->s\)即可(注意我们此时在\(root\),结束在\(s\))

发现\(root\)变了,但是\(s\)经过了两次,相当于没改变,由上可知,肯定合法.

至于\(4n\)的限制

我们发现每个点最多下1步,上1步,来回判不合法2步.但是有叶子的存在,答案是小于\(4n\)

#include<cstdio>
#include<cstring>
#include<iostream>
#include<cctype>
#include<vector>
using namespace std;
const int N = 1e5 + 3;
int tot = 1;
int n,m;
struct edhe{
    int to;
    int nxt;    
}e[N << 1];
int head[N];
int s[N];
bool vis[N];
int now[N];
int size,num1,root;
vector <int> G[N];
vector <int> ans;
inline int read(){
    int v = 0,c = 1;char ch = getchar();
    while(!isdigit(ch)){
        if(ch == '-') c = -1;
        ch = getchar(); 
    }
    while(isdigit(ch)){
        v = v * 10 + ch - 48;
        ch = getchar(); 
    }
    return v * c;
}
inline void add(int x,int y){
    e[++tot].to = y;
    e[tot].nxt = head[x];
    head[x] = tot;  
}
inline void dfs(int x){
    vis[x] = 1;
    size++;num1 += (s[x] == 1);
    for(int i = head[x];i;i = e[i].nxt){
        int y = e[i].to;
        if(!vis[y]) {G[x].push_back(y);dfs(y);}
    }
}
inline void dfs2(int x,int f){
    ans.push_back(x);
    now[x] ^= 1;
    for(int i = 0;i < (int)G[x].size();++i){
        int y = G[x][i];
        dfs2(y,x); 
        ans.push_back(x);
        now[x] ^= 1;
    }
    if(now[x] != s[x] && x != root){
        ans.push_back(f);
        ans.push_back(x);
     //   ans.push_back(f);
        now[x] ^= 1;
        now[f] ^= 1;
    }
    if(now[x] != s[x] && x == root){
        ans.push_back(G[x][0]);
        ans.push_back(root);
        ans.push_back(G[x][0]);
        now[x] ^= 1;
    }
        return ;
}
int main(){
    n = read(),m = read();
    for(int i = 1;i <= m;++i){
        int x = read(),y = read();
        add(x,y);add(y,x);  
    }
    for(int i = 1;i <= n;++i) scanf("%d",&s[i]);
    int g = 0;
    for(int i = 1;i <= n;++i) if(s[i] == 1) g++;    
    if(g == 0){puts("0");return 0;}
    if(m == 0){
        if(g != 1){puts("-1");return 0;}
        else{
            for(int i = 1;i <= n;++i) if(s[i] == 1) {printf("1\n%d\n",i);return 0;}
        }
    }
    for(int i = 1;i <= n;++i){
        if(!vis[i]){
            size = 0,num1 = 0;
            dfs(i);
            if(num1) root = i;
        }
    }
    if(size != n && num1 != g){puts("-1");return 0;}
    dfs2(root,0);
    printf("%d\n",ans.size());
    for(int i = 0;i < (int)ans.size();++i) printf("%d ",ans[i]);
    return 0;   
}