1. 程式人生 > >[Luogu4149][IOI2011]Race

[Luogu4149][IOI2011]Race

ace pre mar div mes class main esp cnblogs

BZOJ權限題qwq
Luogu

sol

樹上路徑當然是澱粉質辣!
考慮所有過重心的路徑。開一個\(10^6\)大小的數組\(t\)表示某一路徑長度的最小邊數,初始化為\(inf(i>0)\)\(t[0]=0\)
枚舉重心的每棵子樹進行\(dfs\),假設獲得了一條從重心出發邊數為\(dep\)邊權和為\(dis\)的路徑,就可以用\(t[K-dis]+dep\)更新答案。
更新完答案後對應用\(dep\)更新\(t[dis]\)
記得還原\(t\)數組。顯然不能直接memset設為\(inf\)。只需把更改過的位置改成\(inf\)即可。

code

#include<cstdio>
#include<algorithm> using namespace std; int gi() { int x=0,w=1;char ch=getchar(); while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar(); if (ch=='-') w=0,ch=getchar(); while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1
)+ch-'0',ch=getchar(); return w?x:-x; } const int inf = 1e9; const int N = 2e5+5; int n,k,to[N<<1],nxt[N<<1],len[N<<1],head[N],cnt; int sz[N],w[N],root,sum,vis[N],t[N*5],ans=inf; void link(int u,int v,int ww) { to[++cnt]=v;nxt[cnt]=head[u];len[cnt]=ww; head[u]=cnt; } void
getroot(int u,int f) { sz[u]=1;w[u]=0; for (int e=head[u];e;e=nxt[e]) { int v=to[e];if (v==f||vis[v]) continue; getroot(v,u); sz[u]+=sz[v];w[u]=max(w[u],sz[v]); } w[u]=max(w[u],sum-sz[u]); if (w[u]<w[root]) root=u; } void getans(int u,int f,int dep,int dis) { if (dis>k) return; ans=min(ans,t[k-dis]+dep); for (int e=head[u];e;e=nxt[e]) { int v=to[e];if (v==f||vis[v]) continue; getans(v,u,dep+1,dis+len[e]); } } void getdp(int u,int f,int dep,int dis) { if (dis>k) return; t[dis]=min(t[dis],dep); for (int e=head[u];e;e=nxt[e]) { int v=to[e];if (v==f||vis[v]) continue; getdp(v,u,dep+1,dis+len[e]); } } void clear(int u,int f,int dep,int dis) { if (dis>k) return; t[dis]=inf; for (int e=head[u];e;e=nxt[e]) { int v=to[e];if (v==f||vis[v]) continue; clear(v,u,dep+1,dis+len[e]); } } void solve(int u) { vis[u]=1; for (int e=head[u];e;e=nxt[e]) if (!vis[to[e]]) getans(to[e],u,1,len[e]),getdp(to[e],u,1,len[e]); for (int e=head[u];e;e=nxt[e]) if (!vis[to[e]]) clear(to[e],u,1,len[e]); for (int e=head[u];e;e=nxt[e]) { int v=to[e];if (vis[v]) continue; sum=sz[v];root=0; getroot(v,0); solve(root); } } int main() { n=gi();k=gi(); for (int i=1,u,v,ww;i<n;++i) { u=gi()+1;v=gi()+1;ww=gi(); link(u,v,ww);link(v,u,ww); } for (int i=1;i<=k;++i) t[i]=inf; sum=w[0]=n; getroot(1,0); solve(root); printf("%d\n",ans==inf?-1:ans); return 0; }

[Luogu4149][IOI2011]Race