2021.11.14 CF1583E Moment of Bloom(LCA+图上构造)
https://www.luogu.com.cn/problem/CF1583E
题意:
She does her utmost to flawlessly carry out a person's last rites and preserve the world's balance of yin and yang.
Hu Tao, being the little prankster she is, has tried to scare you with this graph problem! You are given a connected undirected graph of n nodes with m edges. You also have q queries. Each query consists of two nodes a and b .
Initially, all edges in the graph have a weight of 00 . For each query, you must choose a simple path starting from a and ending at b . Then you add 1 to every edge along this path. Determine if it's possible, after processing all qq queries, for all edges in this graph to have an even weight. If so, output the choice of paths for each query.
If it is not possible, determine the smallest number of extra queries you could add to make it possible. It can be shown that this number will not exceed \(10^{18}\) under the given constraints.
A simple path is defined as any path that does not visit a node more than once.
An edge is said to have an even weight if its value is divisible by 2 .
分析:
https://www.luogu.com.cn/blog/dream-of-Au/solution-cf1583e
如果一条边的边权是偶数,那么这条边的边权对两端端点点权的贡献也是偶数。如果这条边的边权是奇数,那么这条边的边权对两端端点的点权的贡献也是奇数。一条路径两个端点的点权每增加1,它对路径上其他端点点权的贡献为2,毕竟一个端点连着两条边。图上最终每出现两个点权为奇数的点,想要把点权变为偶数,只需要增加1条边。根据题上要求,奇数点的个数一定为偶数。
代码如下:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
#define IOS ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0);
using namespace std;
const int N=3e5+10;
int n,m,q,fa[N][20],cnt,head[N],dep[N],val[N],belong[N],stacki[N];
struct node{
int to,next;
}a[N];
struct queryi{
int x,y;
}query[N];
struct mapii{
int u,v;
}mapi[N];
inline void add(int u,int v){
++cnt;
a[cnt].to=v;
a[cnt].next=head[u];
head[u]=cnt;
}
inline void dfs(int x,int fai){
dep[x]=dep[fai]+1;
fa[x][0]=fai;
for(int i=head[x];i;i=a[i].next){
int v=a[i].to;
if(dep[v])continue;
dfs(v,x);
}
}
inline int lca(int x,int y){
if(dep[x]<dep[y])swap(x,y);
for(int i=19;i>=0;i--)if(fa[x][i]&&dep[fa[x][i]]>=dep[y])x=fa[x][i];
if(x==y)return x;
for(int i=19;i>=0;i--)if(fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i];
return fa[x][0];
}
inline int find(int x){
return belong[x]==x?x:belong[x]=find(belong[x]);
}
inline void print(int x,int y,int lcai){
int now=x;
while(now!=lcai)cout<<now<<" ",now=fa[now][0];
cout<<lcai<<" ";
now=y;
int top=0;
while(now!=lcai)stacki[++top]=now,now=fa[now][0];
for(int i=top;i>=1;i--)cout<<stacki[i]<<" ";cout<<endl;
}
int main(){
cin>>n>>m;
for(int i=1;i<=m;i++)cin>>mapi[i].u>>mapi[i].v;
cin>>q;
for(int i=1;i<=q;i++){
cin>>query[i].x>>query[i].y;
++val[query[i].x];++val[query[i].y];
}
int ans=0;
for(int i=1;i<=n;i++)if(val[i]%2)++ans;
if(ans)return cout<<"NO"<<endl<<ans/2,0;
cout<<"YES"<<endl;
for(int i=1;i<=n;i++)belong[i]=i;
for(int i=1;i<=m;i++){
int ui=find(mapi[i].u),vi=find(mapi[i].v);
if(ui==vi)continue;
belong[ui]=vi;
add(mapi[i].u,mapi[i].v);add(mapi[i].v,mapi[i].u);
//cout<<mapi[i].u<<" "<<mapi[i].v<<endl;//
}
//cout<<" Case 1"<<endl;
dfs(1,0);
//cout<<" Case 2"<<endl;
for(int i=1;i<=19;i++)for(int j=1;j<=n;j++)fa[j][i]=fa[fa[j][i-1]][i-1];
for(int i=1;i<=q;i++){
int x=query[i].x,y=query[i].y;
int lcai=lca(x,y);
//cout<<x<<" "<<y<<" "<<lcai<<endl;
cout<<dep[x]+dep[y]-2*dep[lcai]+1<<endl;
print(x,y,lcai);
}
return 0;
}
posted on
浙公网安备 33010602011771号