Codeforces Round #572 (Div. 2) D2
D2. Add on a Tree: Revolution
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output
Note that this is the second problem of the two similar problems. You can hack this problem if you solve it. But you can hack the previous problem only if you solve both problems.
You are given a tree with ?n nodes. In the beginning, 00 is written on all edges. In one operation, you can choose any 22 distinct leaves ?u, ?vand any integer number ?x and add ?x to values written on all edges on the simple path between ?u and ?v. Note that in previous subtask ?x was allowed to be any real, here it has to be integer.
For example, on the picture below you can see the result of applying two operations to the graph: adding 22 on the path from 77 to 66, and then adding −1−1 on the path from 44 to 55.
You are given some configuration of nonnegative integer pairwise different even numbers, written on the edges. For a given configuration determine if it is possible to achieve it with these operations, and, if it is possible, output the sequence of operations that leads to the given configuration. Constraints on the operations are listed in the output format section.
Leave is a node of a tree of degree 11. Simple path is a path that doesn't contain any node twice.
Input
The first line contains a single integer ?n (2≤?≤10002≤n≤1000) — the number of nodes in a tree.
Each of the next ?−1n−1 lines contains three integers ?u, ?v, ???val (1≤?,?≤?1≤u,v≤n, ?≠?u≠v, 0≤???≤100000≤val≤10000), meaning that there is an edge between nodes ?u and ?v with ???val written on it. It is guaranteed that these edges form a tree. It is guaranteed that all ???val numbers are pairwise different and even.
Output
If there aren't any sequences of operations which lead to the given configuration, output "NO".
If it exists, output "YES" in the first line. In the second line output ?m — number of operations you are going to apply (0≤?≤1050≤m≤105). Note that you don't have to minimize the number of the operations!
In the next ?m lines output the operations in the following format:
?,?,?u,v,x (1≤?,?≤?1≤u,v≤n, ?≠?u≠v, ?x — integer, −109≤?≤109−109≤x≤109), where ?,?u,v — leaves, ?x — number we are adding.
It is guaranteed that if there exists a sequence of operations producing given configuration, then there exists a sequence of operations producing given configuration, satisfying all the conditions above.
D2比之D1确实就难了不少,比赛的时候也是没有敲出来,然后补题的时候,也是一直WA2,但是列写一下,发现自己的代码的数据确实是可以过Test 2的,然后我把double去改成int类型再输出,竟然就A了,好神奇……!
我们可以这样来想这道题,只要满足D1的条件,也就是可以随意改变之后,那么就一定是“YES”了,之后我们需要怎样去改变呢,才能让所有的边都变成我们想要的样子?
我们要从1~N-1,改变这么多条边,我们可以看到改变“u — v”这条边,如果u、v都是叶子节点的话,那么很简单,只用改变u、v即可;但是如果u、v中u是叶子节点,而v不是呢,我们可以把v向u的反方向(也就是不经过u的方向)去找连个叶子节点(并且是一定可以找到两个叶子节点的,因为度是大于2的),然后假设这两个节点分别为fir和sec,那么我们是不是可以把u—v的边权分成两半“val / 2”(题目中又说到“ all ???val numbers are pairwise”说明说有的val都是可以被2整除的),然后我们这么改变u -- fir去加上val / 2,再v -- sec去加上val / 2,最后fir -- sec去减去val / 2岂不是就可以了。那么,另外最悲催的情况,u、v都不是叶子节点的时候,我们可以效仿刚才的做法,u出发得到的节点两个x1、x2,v出发得到的叶子节点两个y1、y2,然后我们x1 -- y1去加上val / 2,然后x2 -- y2去加上val / 2,最后,x1 -- x2减去val / 2,以及y1 -- y2去减去val / 2即可。
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
#define INF 0x3f3f3f3f
#define HalF (l + r)>>1
#define lsn rt<<1
#define rsn rt<<1|1
#define Lson lsn, l, mid
#define Rson rsn, mid+1, r
#define QL Lson, ql, qr
#define QR Rson, ql, qr
#define myself rt, l, r
#define MP(a, b) make_pair(a, b)
#define MP3(a, b, c) MP(MP(a, b), c)
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
const int maxN = 1e5 + 7;
int N, du[maxN], head[maxN], cnt;
vector<pair<pair<int, int>, int>> ans;
struct Eddge
{
int nex, to;
int val;
Eddge(int a=-1, int b=0, int c=0):nex(a), to(b), val(c) {}
}edge[maxN<<1];
inline void addEddge(int u, int v, int val)
{
edge[cnt] = Eddge(head[u], v, val);
head[u] = cnt++;
}
inline void _add(int u, int v, int val) { addEddge(u, v, val); addEddge(v, u, val); }
pair<pair<int, int>, int> path[maxN];
inline int dfs(int u, int fa)
{
if(du[u] == 1) return u;
else
{
for(int i=head[u], v; ~i; i=edge[i].nex)
{
v = edge[i].to;
if(v == fa) continue;
else return dfs(v, u);
}
}
return u;
}
inline void init()
{
cnt = 0;
memset(head, -1, sizeof(head));
}
int main()
{
scanf("%d", &N);
init();
for(int i=1, u, v; i<N; i++)
{
int w;
scanf("%d%d%d", &u, &v, &w);
_add(u, v, w);
du[u]++; du[v]++;
path[i] = MP3(u, v, w);
}
for(int i=1; i<=N; i++) if(du[i] == 2) { printf("NO\n"); return 0; }
printf("YES\n");
for(int i=1, u, v; i<N; i++)
{
tie(u, v) = path[i].first; //u、v就是path[i]的u、v
pair<int, int> UU = {-1, -1};
for(int j=head[u], tv; ~j; j=edge[j].nex)
{
tv = edge[j].to;
if(tv == v) continue;
int tmp = dfs(tv, u);
if(UU.first == -1) UU.first = tmp;
else if(UU.second == -1) { UU.second = tmp; break; }
}
pair<int, int> VV = {-1, -1};
for(int j=head[v], tu; ~j; j=edge[j].nex)
{
tu = edge[j].to;
if(tu == u) continue;
int tmp = dfs(tu, v);
if(VV.first == -1) VV.first = tmp;
else if(VV.second == -1) { VV.second = tmp; break; }
}
if(du[u] == 1) UU = {u, u};
if(du[v] == 1) VV = {v, v};
int real = path[i].second / 2;
ans.push_back(MP3(UU.first, VV.first, real));
ans.push_back(MP3(UU.second, VV.second, real));
if(UU.first != UU.second) ans.push_back(MP3(UU.first, UU.second, -real));
if(VV.first != VV.second) ans.push_back(MP3(VV.first, VV.second, -real));
}
printf("%d\n", (int)ans.size());
for(int i=0; i<ans.size(); i++) printf("%d %d %d\n", ans[i].first.first, ans[i].first.second, ans[i].second);
return 0;
}