CF453C Little Pony and Summer Sun Celebration
题意
给一个无向图, 个点 条边,给定一个 序列 ,如果 ,要求走到这个点奇数次,否则,要求走到这个点偶数次,请你任选起点,输出满足要求的序列长度和经过点的序列,序列长度不能超过 ,若无解则输出 。
分析
-
如果我们走过一个要走奇数次的点,那么它还要被走偶数次。
-
如果我们走过一个要走偶数次的点,那么它还要被走奇数次。
换句话说:
这不就是逻辑非运算吗!
于是问题就变成了:
给一个无向图, 个点 条边,给定一个 序列 ,每次经过第 个点时 ,要求把所有的 变成 。请你任选起点,输出满足要求的序列长度和经过点的序列,序列长度不能超过 ,若无解则输出 。
接下来我们任选一个点作为起点 ,且满足 ,从 出发进行深搜,对于每个走到的点 ,并执行 ,表示走到一次,接下来走 的未被访问的儿子 ,并回溯 ,如果访问完后 还是 ,就走回他的父节点 再走回来,就可以保证 。每次走记得记录路径。
搜索结束后,判断是否有 为 而未被访问过的点,若有,则表明该图不连通且两边都有需要走奇数次的点,显然无解,输出 。
最后判断一下 是否为 ,若是,取消最后一次返回父节点的操作,即序列长度减去 ,就可以输出答案了。
代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int n,m,a[N],ans[4*N],s,root,v[N];
vector<int>e[N];
void dfs(int x,int fa)
{
a[x]=!a[x];
ans[++s]=x;
v[x]=1;
for(int i=0;i<e[x].size();i++)
if(!v[e[x][i]])
{
dfs(e[x][i],x);
a[x]=!a[x];
ans[++s]=x;
}
if(fa>0&&a[x])
{
ans[++s]=fa,ans[++s]=x;
a[fa]=!a[fa],a[x]=!a[x];
}
}
int main()
{
cin>>n>>m;
for(int i=1;i<=m;i++)
{
int u,v;
cin>>u>>v;
e[u].push_back(v);
e[v].push_back(u);
}
for(int i=1;i<=n;i++)
{
cin>>a[i];
if(a[i])
root=i;
}
if(root)
{
dfs(root,0);
for(int i=1;i<=n;i++)
if(a[i]&&!v[i])
{
cout<<-1;
return 0;
}
}
if(a[root])
s--;
cout<<s<<endl;
for(int i=1;i<=s;i++)
cout<<ans[i]<<" ";
return 0;
}

浙公网安备 33010602011771号