[CF901D] Weighting a Tree 题解
想象力惊人的想到生成树,因此对于一种 \(c\) 序列,容易求出只有根不满足要求的构造,且只有树边有权。考虑通过非树边们修改根。
对于一条非树边(都是返祖边),假如我们给它的权值 \(+1\),那么对于奇环来说,\(\Delta root=\pm 2\);偶环没有变化。
所以我们直接找到奇环,分别尝试两种情况即可。时间复杂度 \(O(n)\)。
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int n,m,dep[N],fx,fy,fb,u[N],v[N];
long long c[N],ans[N],wt[N];
struct edge{int to,id;};
vector<edge>ve[N],g[N];
void dfs1(int x){
for(auto y:ve[x]) if(!dep[y.to])
g[x].push_back(y),dep[y.to]=dep[x]+1,dfs1(y.to);
}void dfs2(int x){
wt[x]=0;for(auto y:g[x])
dfs2(y.to),wt[x]+=(ans[y.id]=c[y.to]-wt[y.to]);
}int main(){
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
cin>>n>>m;
for(int i=1;i<=n;i++) cin>>c[i];
for(int i=1,x,y;i<=m;i++){
cin>>x>>y,ve[y].push_back({x,i});
ve[u[i]=x].push_back({v[i]=y,i});
}dfs1(dep[1]=1),dfs2(1);long long dt=wt[1]-c[1];
if(dt){
for(int i=1;i<=m;i++)
if(abs(dep[u[i]]-dep[v[i]])%2==0)
fx=u[i],fy=v[i],fb=i;
if(!fb) return cout<<"NO",0;
c[fx]-=dt/2,c[fy]-=dt/2,dfs2(1);
if(wt[1]!=c[1])
c[fx]+=dt,c[fy]+=dt,dfs2(1),ans[fb]=-dt/2;
else ans[fb]=dt/2;
}cout<<"YES\n";
for(int i=1;i<=m;i++)
cout<<ans[i]<<"\n";
return 0;
}

浙公网安备 33010602011771号