EZOJ #79
分析
在经过若干次操作之后一定会产生一堆环
而我们又发现从一个点到另一个点实际可以经过所有环
于是问题就转换成了$k_1s_1 + k_2s_2 + ... + len = t$
其中$s_i$为每个环的长度,$len$为两点间距离
于是每次gcd求一下就行了
注意两点间距离不用求LCA,用深度值减一下就可以了
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cctype>
#include<cmath>
#include<cstdlib>
#include<queue>
#include<ctime>
#include<vector>
#include<set>
#include<map>
#include<stack>
using namespace std;
long long d[100100];
vector<pair<int,int> >v[100100];
inline void dfs(int x,int fa){
long long i,j,k;
for(i=0;i<v[x].size();i++){
int y=v[x][i].first,z=v[x][i].second;
if(y==fa)continue;
d[y]=d[x]+z;
dfs(y,x);
}
return;
}
inline long long gcd(long long x,long long y){return y==0?x:gcd(y,x%y);}
int main(){
int n,m,i,j,k;
long long res=-1;
scanf("%d%d",&n,&m);
for(i=1;i<n;i++){
int x,y;
int z;
scanf("%d%d%d",&x,&y,&z);
v[x].push_back(make_pair(y,z));
v[y].push_back(make_pair(x,-z));
}
d[1]=0;
dfs(1,0);
for(i=1;i<=m;i++){
int x,y;
int z;
scanf("%d",&k);
scanf("%d%d%d",&x,&y,&z);
if(k==0){
long long t=d[x]-d[y]+z;
if(res==-1){
res=abs(t);
}else {
res=gcd(res,abs(t));
}
}else {
long long t=d[y]-d[x]-z;
if(res!=-1){
if(abs(t)%res==0)puts("yes");
else puts("no");
}else {
if(t==0)puts("yes");
else puts("no");
}
}
}
return 0;
}