CF1166F Vicky's Delivery Service
最近太摆了,写一篇题解。
只走偶数步是很好处理的,直接用map存一下之后上并查集。
主要是还有奇数步,这个的话就可以用set存每个连通块可以小于等于一步走到的点了。
当然合并的时候要把set也合并上,用启发式合并就好了,反正存的东西 \(\le m\)。
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
map<int,int>id[N];
map<int,vector<int>>e[N];
int n,m,c,q,tot,f[N*10];
set<int>s[N*10];
int find(int x)
{
if(f[x]==x)return x;
return f[x]=find(f[x]);
}
void merge(int x,int y)
{
x=find(x),y=find(y);
if(x==y)return;
if(s[x].size()<s[y].size())swap(x,y);
for(int t:s[y])s[x].insert(t);
f[y]=x;
return;
}
int main()
{
scanf("%d%d%d%d",&n,&m,&c,&q),tot=n;
for(int i=1;i<=n;i++)f[i]=i,s[i].insert(i);
for(int i=1,u,v,w;i<=m;i++)
{
scanf("%d%d%d",&u,&v,&w);
e[u][w].push_back(v);
e[v][w].push_back(u);
s[u].insert(v),s[v].insert(u);
}
for(int i=1;i<=n;i++)
{
for(auto it:e[i])
{
id[i][it.first]=++tot,f[tot]=tot;
for(int v:it.second)merge(v,tot);
}
}
while(q--)
{
int u,v,w;
char op;
cin>>op;
scanf("%d%d",&u,&v);
if(op=='+')
{
scanf("%d",&w);
s[find(u)].insert(v);
s[find(v)].insert(u);
if(id[u][w])merge(v,id[u][w]);
else id[u][w]=++tot,f[tot]=tot,merge(v,tot);
if(id[v][w])merge(u,id[v][w]);
else id[v][w]=++tot,f[tot]=tot,merge(u,tot);
}
else
{
if(find(u)!=find(v)&&!s[find(u)].count(v))printf("No\n");
else printf("Yes\n");
}
}
return 0;
}

浙公网安备 33010602011771号