3 条题解
-
1
带权并查集,核心思想就是将边权下放到点上,从而利用类似于前缀和的思想快速求出两点间的边权,核心难点便是连边时权值的处理方式。
对于这道题,我们先不考虑取模的问题,直接假定题目给出的是 (看清楚 和 ),那么假设 为 到它所在的树的根节点的边权之和。显然,对于同一颗树内的任意两点 ,对于 这条边的边权 ,必然有 ,则 。
root 5/ 1 \4 u - > v接下来考虑两颗不同树内的节点 ,分别找到根 。从 向 连一条边权为 的边( 到 也可以),接下来,我们假设从 向 连一条边,易得这条边的边权为 ,所以有 ,所以 。
5-1-2 a<---------b ^ ^ | /| | / | | / | | / | 5| 1+2/ |2 | / | | / | | / | | / | |/ | u--------->v 1在此题中,记得取模就行。
代码:
#include<bits/stdc++.h> using namespace std; const long long mod=998244353; long long dis[200005]; int fa[200005]; int find(int x){ if(fa[x]==x){ return x; } int to=find(fa[x]); dis[x]=(dis[x]+dis[fa[x]])%mod; return fa[x]=to; } int main(){ int n,q; cin>>n>>q; for(int i=0;i<n;i++){ fa[i]=i; } while(q--){ int op; cin>>op; if(op==0){ long long u,v,k; cin>>u>>v>>k; int a=find(u),b=find(v); if(a!=b){ fa[b]=a; dis[b]=(dis[u]-dis[v]-k+mod*3)%mod; cout<<1<<"\n"; } else{ if((dis[u]-dis[v]+mod*2)%mod==k){ cout<<1<<"\n"; } else{ cout<<0<<"\n"; } } } else{ int u,v; cin>>u>>v; int a=find(u),b=find(v); if(a!=b){ cout<<"-1\n"; } else{ cout<<(dis[u]-dis[v]+mod*2)%mod<<"\n"; } } } return 0; } -
0
放个注释代码喵
#include<bits/stdc++.h> using namespace std; typedef long long LL; const LL P = 998244353; const int N = 2e5 + 10; LL dis[N]; int fa[N]; int findfa(int x) { if (x == fa[x]) { return fa[x]; } int to = findfa(fa[x]); dis[x] = (dis[x] + dis[fa[x]]) % P; return fa[x] = to; } int main () { ios::sync_with_stdio(false); cin.tie(0); int n, Q; cin >> n >> Q; for (int i = 0; i < n; i ++) { fa[i] = i; dis[i] = 0; } while (Q --) { int opt; cin >> opt; if (opt == 0) { int u, v; LL k; cin >> u >> v >> k; // a[u] = a[v] + k // a[u] - a[v] = k int fu = findfa(u), fv = findfa(v); if (fu != fv) { fa[fv] = fu; // dis[u] = a[fu] - a[u] // dis[v] = a[fv] - a[v] // a[fu] - a[fv] = dis[u] - a[u] - dis[v] + a[v] dis[fv] = (dis[u] - dis[v] - k + 3 * P) % P; cout << "1\n"; } else { if ((dis[u] - dis[v] + 2 * P) % P == k) { cout << "1\n"; } else { cout << "0\n"; } } } else { int u, v; cin >> u >> v; int fu = findfa(u), fv = findfa(v); if (fu != fv) { cout << "-1\n"; } else { cout << (dis[u] - dis[v] + 2 * P) % P << "\n"; } } } return 0; } -
0
#include<bits/stdc++.h> using namespace std; #define int long long #define pii pair<int,int> #define fi first #define se second #define N 200010 #define mod 998244353 int n,q,fa[N],d[N]; int findfa(int x){ if(fa[x]!=x){ int top=findfa(fa[x]); d[x]=(d[x]+d[fa[x]])%mod; fa[x]=top; } return fa[x]; } signed main(){ ios::sync_with_stdio(0);cin.tie(0);cout.tie(0); cin>>n>>q; for(int i=0;i<n;i++)fa[i]=i,d[i]=0; while(q--){ int op;cin>>op; if(op==0){ int x,y,a;cin>>x>>y>>a; a=(a%mod+mod)%mod; int tx=findfa(x),ty=findfa(y); if(tx!=ty){ fa[ty]=tx; d[ty]=((d[x]-d[y]-a)%mod+mod)%mod; cout<<"1\n"; } else{ if(((d[x]-d[y])%mod+mod)%mod==a)cout<<"1\n"; else cout<<"0\n"; } } else{ int x,y;cin>>x>>y; int tx=findfa(x),ty=findfa(y); if(tx!=ty){ cout<<"-1\n"; } else{ cout<<((d[x]-d[y])%mod+mod)%mod<<'\n'; } } } return 0; }
- 1
信息
- ID
- 8121
- 时间
- 1000ms
- 内存
- 1024MiB
- 难度
- 7
- 标签
- 递交数
- 76
- 已通过
- 17
- 上传者