8.13集訓
阿新 • • 發佈:2020-08-13
上午
考試
下午
改題
第一題
給出一顆n個點的樹,從1號點出發走m步,每步一條邊,最多可以經過多少點?點和邊均可以重複經過,但重複的點只計算一次。
顯然,我們需要找出距離1號點最遠的邊,這些邊都只走一次,別的邊走兩次
考慮三種情況:
- 1,m過於大,即使把整個圖都跑完也用不完m
- 2,m剛好可以跑完那個距離1號點的最長鏈
- 3,m可以跑完那個鏈,還有剩餘
#include <bits/stdc++.h> #define LL long long #define debug using namespace std; //東方之珠 整夜未眠! const int N = 3e5+66; int d[N]; struct node {int to, nex;}e[N<<1]; int head[N], cnt; inline void jiabian(int u, int v) { e[++ cnt].to = v; e[cnt].nex = head[u]; head[u] = cnt; } inline int dfs(int x, int fa) { int i; for (i = head[x]; i; i = e[i].nex) { int y = e[i].to; if (y == fa) continue; d[y] = d[x] + 1; dfs(y, x); } } inline int thestars() { int i, j, k, n, m, res(0); cin >> n >> m; for (i = 1; i < n; ++ i) { int x, y; cin >> x >> y; jiabian(x, y); } dfs(1, 0); for (i = 2; i <= n; ++ i) { if (res < d[i]) { res = d[i]; } } if (m <= res) cout << m + 1; else if (m >= res + 2 * (n - res - 1)) cout << n; else cout << res + (m - res)/2 + 1; return 0; } int youngore = thestars(); signed main() {;}
第二題
給出一棵n個點的樹,第i個點的權值為\(a_i\),現在你可以進行如下操作:
- 1,選擇一個包含1號點的連通子圖,使其中所有點權值+1
- 2,選擇一個包含1號點的連通子圖,使其中所有點權值-1
求最小的操作次數,使得所有點的權值都變為0
第一次看見我以為是關於差分的題,就像這道一樣
於是我一直在想樹上差分,一直在想,一直在想,可是考完試我才發現,跟tm差分沒一點關係,
如果我沒有一直往差分那裡鑽,或許我還能想到一些暴力的做法,
想到差分,註定了我只能拿零分
給出gxz的題解:
設\(f[i]\)表示以i為根的子樹需要進行-1操作的次數,則需要進行+1操作的次數為\(f[i]-a[i]\)
考慮一個點,不考慮自身的話,需要進行的\(-1\)和\(+1\)操作都是所有子節點的最大值。
故記\(M = Max(f[son]),N = Max(f[son]-a[son])\),子樹至少要減\(M\)次,自己至少要減\(N+a_i\)次
得到\(f[i] =Max(M, N+a[i])\)
最終答案為\(f[1]+(f[1]+a[1])\)
#include <bits/stdc++.h> #define int long long #define debug using namespace std; //東方之珠 整夜未眠! const int N = 3e5+66; int f[N], a[N]; struct node {int to, nex;}e[N<<1]; int head[N<<1], cnt; inline void add(int u, int v) { e[++ cnt].to = v; e[cnt].nex = head[u]; head[u] = cnt; } inline void dfs(int x, int fa) { int i, M(0), N(0); for (i = head[x]; i; i = e[i].nex) { int y = e[i].to; if (y == fa) continue; dfs(y, x); M = max(M, f[y]); N = max(N, f[y] - a[y]); } f[x] = max(M, N + a[x]); } inline int thestars() { int i, j, k, n, m, res(0); cin >> n; for (i = 1; i < n; ++ i) { int x, y; cin >> x >> y; add(x, y); add(y, x); } for (i = 1; i <= n; ++ i) scanf ("%lld", &a[i]); dfs(1, 0); cout << (f[1] + f[1] - a[1]); fclose (stdin), fclose (stdout); return 0; } int youngore = thestars(); signed main() {;}
注意開LL
第三題
給出gxz題解:
發誓再也tm不用cin了
#include <bits/stdc++.h>
#define LL long long
#define debug
using namespace std;
//東方之珠 整夜未眠!
const int N = 5e5+66;
const double eps = 1e-7;
double w[N], f[N], g[N];
struct node {int to, nex; double val;}e[N<<1]; int head[N<<1], cnt;
inline void add(int x, int y, double z) {
e[++ cnt].to = y;
e[cnt].val = z;
e[cnt].nex = head[x];
head[x] = cnt;
}
inline void dfs1(int x, int fa) {
int i;
f[x] = 1 - w[x];
for (i = head[x]; i; i = e[i].nex) {
int y = e[i].to;
if (y == fa) continue;
dfs1(y, x);
f[x] *= 1 - f[y] * e[i].val;//cong 0 tui dao 1
}
f[x] = 1 - f[x]; //f[x] cong biao shi 0 bian cheng le biao shi 1
}
inline void dfs2(int x, int fa) {
int i;
for (i = head[x]; i; i = e[i].nex) {
int y = e[i].to;
if (y == fa) continue;
if (1 - f[y] * e[i].val < eps) g[y] = 1;
else g[y] = 1 - (1 - f[y]) * (1 - (1 - (1 - g[x]) / (1 - f[y] * e[i].val)) * e[i].val);
dfs2(y, x);
}
}
inline int thestars() {
int i, j, k, x, y, n;
double z, res(0);
cin >> n;
for (i = 1; i < n; ++ i) {
scanf ("%d%d%lf", &x, &y, &z);
add(x, y, z/100);
add(y, x, z/100);
}
for(i = 1 ; i <= n ; i ++ ) scanf("%lf" , &w[i]) , w[i] /= 100;
dfs1(1, 0);
g[1] = f[1];
dfs2(1, 0);
for (i = 1; i <= n; ++ i) res += g[i];
printf ("%.6lf\n" , res);
return 0;
}
int youngore = thestars();
signed main() {;}