- 能不能达到目标结构的条件就是上个subtask讨论过的,只要没有度为2的点就可以
- 接下来讨论每条边如何变成需要的值,对于一条路,假如两个端点它们都是非叶子节点,记作A,B,取A的不同子树(不包含B)上的两个叶子a1,a2,B的两个不同子树(不包含A)上的两个叶子b1,b2,那么若AB间的路要达到某个值val,a1到b1加val/2,a2到b2加val/2,再使a1到a2减val/2,b1到b2减val/2即可。假如一个端点是叶子而另一个是非叶子,操作也类似。用这个方法证明了的确可以使得树的边权达到任意值。
#include <bits/stdc++.h>
using namespace std;
struct edg
{
int x, y, z;
};
int n;
int deg[1005];
vector<int> adj[1005];
vector<edg> tar;
vector<edg> ans;
void insert()
{
cin >> n;
for (int i = 0; i <= n; i++)
{
deg[i] = 0;
}
for (int i = 0; i < n - 1; i++)
{
int x, y, z;
edg e;
cin >> x >> y >> z;
e.x = x, e.y = y, e.z = z;
tar.push_back(e);
adj[x].push_back(y);
adj[y].push_back(x);
deg[x]++, deg[y]++;
}
}
bool yn()
{
for (int i = 1; i <= n; i++)
{
if (deg[i] == 2)
{
return false;
}
}
return true;
}
int leaf(int r, int com)
{
if (deg[r] == 1)
return r;
else if (adj[r][0] == com)
return leaf(adj[r][1], r);
else
return leaf(adj[r][0], r);
}
void getans()
{
for (int j = 0; j < tar.size(); j++)
{
int a, b, c, d;
a = b = c = d = 0;
int u = tar[j].x;
int v = tar[j].y;
for (int i = 0; i < adj[u].size(); i++)
{
if (adj[u][i] == v)
continue;
if (a == 0)
{
a = leaf(adj[u][i],u);
}
else
{
b = leaf(adj[u][i],u);
break;
}
}
for (int i = 0; i < adj[v].size(); i++)
{
if (adj[v][i] == u)
continue;
if (c == 0){
c = leaf(adj[v][i],v);
}
else
{
d = leaf(adj[v][i],v);
break;
}
}
int val = tar[j].z;
edg e1, e2, e3;
if(a==0&&c==0){
e1.x=u,e1.y=v,e1.z=val;
ans.push_back(e1);
}
else if (a==0)
{
e1.x = u, e1.y = c, e1.z = val / 2;
e2.x = u, e2.y = d, e2.z = val / 2;
e3.x = c, e3.y = d, e3.z = -val / 2;
ans.push_back(e1);
ans.push_back(e2);
ans.push_back(e3);
}
else if (c == 0)
{
e1.x = a, e1.y = v, e1.z = val / 2;
e2.x = b, e2.y = v, e2.z = val / 2;
e3.x = a, e3.y = b, e3.z = -val / 2;
ans.push_back(e1);
ans.push_back(e2);
ans.push_back(e3);
}
else
{
edg e4;
e1.x = a, e1.y = c, e1.z = val / 2;
e2.x = b, e2.y = d, e2.z = val / 2;
e3.x = a, e3.y = b, e3.z = -val / 2;
e4.x = c, e4.y = d, e4.z = -val / 2;
ans.push_back(e1);
ans.push_back(e2);
ans.push_back(e3);
ans.push_back(e4);
}
}
}
void printans()
{
cout << ans.size() << endl;
for (int i = 0; i < ans.size(); i++)
cout << ans[i].x << " " << ans[i].y << " " << ans[i].z << endl;
}
int main()
{
insert();
if (!yn())
{
cout << "NO" << endl;
return 0;
}
cout << "YES" << endl;
getans();
printans();
return 0;
}
好了,卡了很久的原因居然是漏了考虑只有两个节点的情况,也就是说最上面的分析还应该加上两个点都是叶子节点的情况。
另外还要注意的点是,深搜的时候,注意不要搜到父亲节点。