感觉好像有点思路,试着写了一个#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
const uint64_t mod = 1000000007;
struct edge{
int64_t weight;
uint32_t destination;
uint32_t next;
};
struct edge edges[(unsigned int)4e5];
uint32_t head[(unsigned int)2e5 + 1];
uint32_t next_edge;
uint32_t n;
int64_t l, r;
void insert_edge(uint32_t source, uint32_t destination, int64_t weight){
edges[next_edge].weight = weight;
edges[next_edge].destination = destination;
edges[next_edge].next = head[source];
head[source] = next_edge++;
}
void trace(
uint32_t target,
int64_t p_weight, int64_t p_low, int64_t p_high,
int64_t* c_low, int64_t* c_high
){
uint32_t start = head[target];
int64_t low = p_weight - p_high;
int64_t high = p_weight - p_low;
head[target] |= 1 << 31;
int64_t child_low, child_high;
for(uint32_t edge = start; edge != 0x7fffffff; edge = edges[edge].next){
if(head[edges[edge].destination] >> 31 == 1) continue;
if(edges[edge].weight - low < l || edges[edge].weight - high > r){
low = 1;
high = 0;
break;
}
if(edges[edge].weight - r > low) low = edges[edge].weight - r;
if(edges[edge].weight - l < high) high = edges[edge].weight - l;
trace(edges[edge].destination, edges[edge].weight, low, high, &child_low, &child_high);
if(child_low > child_high){
low = 1;
high = 0;
break;
}
if(edges[edge].weight - child_high > low) low = edges[edge].weight - child_high;
if(edges[edge].weight - child_low < high) high = edges[edge].weight - child_low;
}
*c_low = low;
*c_high = high;
}
void group_main(){
uint64_t result = 1;
scanf("%u%ld%ld", &n, &l, &r);
int64_t minimum_weight = l + l;
int64_t maximum_weight = r + r;
for(uint32_t i = 1; i <= n; i++) head[i] = 0x7fffffff;
next_edge = 0;
uint8_t op;
uint32_t source, destination;
int64_t weight;
for(uint32_t i = 1; i < n; i++){
scanf("%hhu", &op);
if(op == 0) scanf("%*u%*u");
else if(op == 1){
scanf("%u%u%ld", &source, &destination, &weight);
if(weight > maximum_weight || weight < minimum_weight){
printf("0\n");
return;
}
insert_edge(source, destination, weight);
insert_edge(destination, source, weight);
}
}
int64_t left, right;
for(uint32_t i = 1; i <= n; i++){
if(head[i] >> 31 == 0){
trace(i, l + r, l, r, &left, &right);
if(left > right){
result = 0;
break;
}
result = ((right - left + 1) * result) % mod;
if(result == 0) break;
}
}
printf("%lu\n", result);
}
int main(){
uint8_t T;
scanf("%hhu", &T);
for(uint8_t i = 0; i < T; i++) group_main();
return 0;
}
|