題目鏈接
這題有一個規律的東西,就是我們實際上只需要看1、2的鏈,譬如說有一個大於2權值爲k的點,如果它的周圍有權值爲1的點的話,那麼我們實際上沒有必要去選上k,只需要選1即可,因爲若是選上權值爲k的話,,那麼需要使得要取的值爲1的點的個數爲x的情況下:,又有,所以必須存在一條存在點度大於2的鏈,顯然,這是不現實的,所以我們只需要考慮1、2兩個點就是了,0的時候答案自然爲“0/1”,若是沒有1、2和0那肯定就是每個點“minn/1”就是了。
所以,關於2,還是要特殊的,需要保證的是,2的兩邊的x數量是對等的,若是有一邊偏大,那麼直接選那一邊不是更好嗎?
然後我們維護這個式子,去找最大的滿足條件的x。所以,這裏可以向上遞推的來解決。
我們還需要維護一個表示u這個點向下只走“1”的最遠能到達的距離。
10
1 2
1 3
1 4
2 5
2 6
3 7
6 8
8 9
7 10
1 3 3 2 1 1 1 3 1 2
ans:1/1
5
1 2
2 3
3 4
4 5
1 1 2 1 1
ans:2/5
3
1 2
1 3
2 1 1
ans:2/3
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <bitset>
#include <unordered_map>
#include <unordered_set>
#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
using namespace std;
typedef unsigned long long ull;
typedef unsigned int uit;
typedef long long ll;
struct pir
{
int fir, sec;
pir(int a=0, int b=0):fir(a), sec(b) {}
friend bool operator < (pir e1, pir e2) { return e1.fir == e2.fir ? e1.sec > e2.sec : e1.fir > e2.fir; }
friend bool operator == (pir e1, pir e2) { return e1.fir == e2.fir; }
};
inline int gcd(int a, int b) { return b ? gcd(b, a % b) : a; }
const int maxN = 1e6 + 7;
int N, head[maxN], cnt;
struct Eddge
{
int nex, to;
Eddge(int a=-1, int b=0):nex(a), to(b) {}
} edge[maxN << 1];
inline void addEddge(int u, int v)
{
edge[cnt] = Eddge(head[u], v);
head[u] = cnt++;
}
inline void _add(int u, int v) { addEddge(u, v); addEddge(v, u); }
int a[maxN], ans[2], deep[maxN], dp[maxN];
pir vt[maxN];
void Min(int *x, int y[2])
{
if(1LL * x[0] * y[1] > 1LL * x[1] * y[0]) { x[0] = y[0]; x[1] = y[1]; }
}
void dfs(int u, int fa)
{
int tmp[2];
for(int i=head[u], v; ~i; i=edge[i].nex)
{
v = edge[i].to;
if(v == fa) continue;
deep[v] = (a[v] == 1 ? deep[u] + 1 : 0);
dfs(v, u);
if(a[u] == 1)
{
tmp[0] = 1; tmp[1] = dp[u] + 1 + dp[v];
Min(ans, tmp);
if(vt[v] < vt[u])
{
vt[u] = vt[v];
if(vt[u].sec + 1 + dp[u] == vt[u].fir)
{
tmp[0] = 2; tmp[1] = 1 + 2 * vt[u].fir;
Min(ans, tmp);
}
}
else
{
if(vt[u].sec + 1 + dp[v] == vt[u].fir)
{
tmp[0] = 2; tmp[1] = 1 + 2 * vt[u].fir;
Min(ans, tmp);
}
}
}
else if(a[u] == 2)
{
tmp[0] = 2; tmp[1] = 2 * min(dp[u], dp[v]) + 1;
Min(ans, tmp);
}
dp[u] = max(dp[u], dp[v]);
}
if(a[u] == 1)
{
dp[u] ++;
vt[u].sec ++;
}
else if(a[u] == 2)
{
if(deep[fa] >= dp[u])
{
tmp[0] = 2; tmp[1] = 2 * dp[u] + 1;
Min(ans, tmp);
}
else vt[u] = pir(dp[u], 0);
dp[u] = 0;
}
else { dp[u] = 0; vt[u] = pir(INF, 0); }
tmp[0] = 1; tmp[1] = dp[u];
Min(ans, tmp);
}
inline void init()
{
cnt = 0; ans[0] = INF; ans[1] = 1;
for(int i=1; i<=N; i++) head[i] = -1;
}
int main()
{
scanf("%d", &N);
init();
for(int i=1, u, v; i<N; i++)
{
scanf("%d%d", &u, &v);
_add(u, v);
}
for(int i=1; i<=N; i++)
{
int tmp[2];
scanf("%d", &a[i]);
tmp[0] = a[i]; tmp[1] = 1;
Min(ans, tmp);
}
deep[1] = (a[1] == 1 ? 1 : 0);
dfs(1, 0);
int _GCD = gcd(ans[0], ans[1]);
printf("%d/%d\n", ans[0] / _GCD, ans[1] / _GCD);
return 0;
}