Codeforces 1189D2. Add on a Tree: Revolution

传送门

首先可以证明一颗树合法的充分必要条件是不存在某个节点的度数为 $2$

首先它是必要的,考虑任意一条边连接的两点如果存在某一点 $x$ 度数为 $2$ ,那么说明 $x$ 还有连一条边出去,那么连出去的那一条边和当前边的权值就永远一样

然后它是充分的,考虑进行如下操作:首先设当前边连接的两端分别为 $L,R$ ,如果 $L,R$ 只要存在某一个度数为 $1$ 显然合法

然后考虑 $L,R$ 度数不为 $1$ 的情况,那么 $L,R$ 一定分别存在两个儿子连向叶子,设为 $Lx,Ly,Rx,Ry$ 

设当前边的目标权值为 $x$ ,那么只要操作: $(Lx,Rx,x/2),(Ly,Ry,x/2),(Lx,Ly,-x),(Rx,Ry,-x)$ 即可,由于 $x$ 为偶数,所以 $x/2$ 一定为整数

因为这一题可以 $n^2$ ,所以直接按上面描述模拟即可

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<vector>
using namespace std;
typedef long long ll;
inline int read()
{
    int x=0,f=1; char ch=getchar();
    while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); }
    while(ch>='0'&&ch<='9') { x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); }
    return x*f;
}
const int N=1e5+7;
int n,a[N],b[N],c[N],du[N];
int fir[N],from[N<<1],to[N<<1],cntt;
inline void add(int a,int b) { from[++cntt]=fir[a]; fir[a]=cntt; to[cntt]=b; }
int find(int x,int fa)
{
    if(du[x]==1) return x;
    for(int i=fir[x];i;i=from[i])
        if(to[i]!=fa) return find(to[i],x);
}
struct dat {
    int x,y,z;
    dat (int _x=0,int _y=0,int _z=0) { x=_x,y=_y,z=_z; }
};
vector <dat> ans;
int main()
{
    n=read();
    for(int i=1;i<n;i++)
    {
        a[i]=read(),b[i]=read(); c[i]=read();
        add(a[i],b[i]); add(b[i],a[i]);
        du[a[i]]++,du[b[i]]++;
    }
    if(n==2) { printf("YES\n1\n1 2 %d\n",c[1]); return 0; }
    for(int i=1;i<n;i++)
    {
        if(du[a[i]]==2||du[b[i]]==2) { printf("NO\n"); return 0; }
        if(du[b[i]]==1) swap(a[i],b[i]);
        vector <int> L,R;
        for(int j=fir[a[i]];j;j=from[j])
            if(to[j]!=b[i]) L.push_back(find(to[j],a[i]));
        for(int j=fir[b[i]];j;j=from[j])
            if(to[j]!=a[i]) R.push_back(find(to[j],b[i]));
        if(L.size()==0)
            ans.push_back(dat(a[i],R[0],c[i]/2)),
            ans.push_back(dat(a[i],R[1],c[i]/2)),
            ans.push_back(dat(R[0],R[1],-c[i]/2));
        else
            ans.push_back(dat(L[0],R[0],c[i]/2)),
            ans.push_back(dat(L[1],R[1],c[i]/2)),
            ans.push_back(dat(L[0],L[1],-c[i]/2)),
            ans.push_back(dat(R[0],R[1],-c[i]/2));
    }
    printf("YES\n%d\n",int(ans.size()));
    for(auto A: ans) printf("%d %d %d\n",A.x,A.y,A.z);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/LLTYYC/p/11728910.html
今日推荐