码迷,mamicode.com
首页 > 其他好文 > 详细

[Luogu4149][IOI2011]Race

时间:2018-02-23 22:25:37      阅读:165      评论:0      收藏:0      [点我收藏+]

标签:head   路径   http   ==   show   答案   names   log   root   

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

标签:head   路径   http   ==   show   答案   names   log   root   

原文地址:https://www.cnblogs.com/zhoushuyu/p/8463265.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!