Live2D

2022/02/10 模拟赛题解

T1

Solution#

比较水,就不说了。

T2

Solution#

就是暴力优化,不知道复杂度为哈对,代码也过不了,就不放了。

T3

Solution#

考虑暴力,即每次每个点向可以一波传染的点连边,然后缩点,求无入度的点数即可。

考虑优化,你发现对于两个点可以在点分树上一个点考虑先走到该点再到另一个点,所以我们可以直接淀粉质,然后双指针拆点连边即可。

Code#

Copy
#include <bits/stdc++.h> using namespace std; #define Int register int #define ll long long #define MAXM 6000005 #define MAXN 300005 template <typename T> inline void read (T &t){t = 0;char c = getchar();int f = 1;while (c < '0' || c > '9'){if (c == '-') f = -f;c = getchar();}while (c >= '0' && c <= '9'){t = (t << 3) + (t << 1) + c - '0';c = getchar();} t *= f;} template <typename T,typename ... Args> inline void read (T &t,Args&... args){read (t);read (args...);} template <typename T> inline void write (T x){if (x < 0){x = -x;putchar ('-');}if (x > 9) write (x / 10);putchar (x % 10 + '0');} template <typename T> inline void chkmax (T &a,T b){a = max (a,b);} template <typename T> inline void chkmin (T &a,T b){a = min (a,b);} int n,m,r[MAXN]; struct edge{ int v,w; }; vector <int> E[MAXM]; vector <edge> g[MAXN]; stack <int> S; bool vis[MAXM]; int ind,tot,dfn[MAXM],low[MAXM],bel[MAXM]; void tarjan (int u){ S.push (u),vis[u] = 1,dfn[u] = low[u] = ++ ind; for (Int v : E[u]) if (!dfn[v]) tarjan (v),chkmin (low[u],low[v]); else if (vis[v]) chkmin (low[u],dfn[v]); if (dfn[u] == low[u]){ ++ tot; while (1){ int now = S.top();S.pop (); bel[now] = tot,vis[now] = 0; if (now == u) break; } } } ll dep[MAXN]; int all,root,siz[MAXN],mxs[MAXN]; void findroot (int u,int fa){ siz[u] = 1,mxs[u] = 0; for (edge it : g[u]){ int v = it.v,w = it.w; if (v == fa || vis[v]) continue; findroot (v,u),chkmax (mxs[u],siz[v]),siz[u] += siz[v]; } chkmax (mxs[u],all - siz[u]); if (!root || mxs[u] < mxs[root]) root = u; } int cnt,tS[MAXN],pS[MAXN]; void dfs (int u,int fa,ll dpt){ pS[cnt] = u,tS[cnt] = u,cnt ++,dep[u] = dpt; for (edge it : g[u]){ int v = it.v,w = it.w; if (v == fa || vis[v]) continue; dfs (v,u,dpt + w); } } void link (int u,int v){ E[u].push_back (v); } void workit (int u){ vis[u] = 1,cnt = 0,dfs (u,0,0); sort (tS,tS + cnt,[](int x,int y){return dep[x] < dep[y];}); sort (pS,pS + cnt,[](int x,int y){return r[x] - dep[x] < r[y] - dep[y];}); for (Int i = 0,t = 0;i < cnt;++ i){ int x = pS[i]; if (r[x] - dep[x] < 0) continue; ++ m;if (t) link (m,m - 1);link (x,m); while (t < cnt && dep[tS[t]] <= r[x] - dep[x]) link (m,tS[t]),++ t; } for (edge it : g[u]){ int v = it.v; if (vis[v]) continue; all = siz[v],root = 0,findroot (v,0),workit (root); } } signed main(){ freopen ("infect.in","r",stdin); freopen ("infect.out","w",stdout); read (n); for (Int i = 1;i <= n;++ i) read (r[i]); for (Int i = 2,u,v,w;i <= n;++ i) read (u,v,w),g[u].push_back ({v,w}),g[v].push_back ({u,w}); m = all = n,findroot (1,0),workit (root),memset (vis,0,sizeof (vis)); for (Int i = 1;i <= m;++ i) if (!dfn[i]) tarjan (i); for (Int u = 1;u <= m;++ u) for (Int v : E[u]) if (bel[u] != bel[v]) vis[bel[v]] = 1; int ans = 0; for (Int i = 1;i <= tot;++ i) ans += (!vis[i]); write (ans),putchar ('\n'); return 0; }
posted @   Dark_Romance  阅读(54)  评论(2编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示
CONTENTS