2599: [IOI2011]Race|树的点分治

来源:互联网 发布:linux连不通数据库端口 编辑:程序博客网 时间:2024/04/30 16:20

数据范围:n200000,K1000000(题意描述中怎么没有。。
然后就是分治,找经过根的路径开数组存下距离为x时的最小边数cnt[x]不断更新答案
点的编号从零开始!!!!(sb不好好看题WA了那么多发还好意思说QAQ

#include<cstdio>#include<cstdlib>#include<cstring>#include<cmath>#include<queue>#include<vector>#include<set>#include<map>#include<iostream>#include<algorithm>#define N 400022#define M 1000002using namespace std;int sc(){    int i=0,f=1; char c=getchar();    while(c>'9'||c<'0'){if(c=='-')f=-1;c=getchar();}    while(c>='0'&&c<='9')i=i*10+c-'0',c=getchar();    return i*f;}int vis[N],size[N],mx[N],dis[N];int head[N],nxt[N],lst[N],v[N];int cnt[M],n,K,sum,root,tot,ans,top,pre;pair<int,int> w[N];void insert(int x,int y,int z){    lst[++tot]=y;nxt[tot]=head[x];head[x]=tot;v[tot]=z;    lst[++tot]=x;nxt[tot]=head[y];head[y]=tot;v[tot]=z;}void get_root(int x,int f){    size[x]=1;mx[x]=0;    for(int i=head[x];i;i=nxt[i])        if(lst[i]!=f&&!vis[lst[i]])        {            get_root(lst[i],x);            size[x]+=size[lst[i]];            mx[x]=max(mx[x],size[lst[i]]);        }    mx[x]=max(mx[x],sum-size[x]);    if(mx[x]<mx[root])root=x;}void dfs(int x,int f,int step,int dis){    if(dis>K)return ;    ans=min(ans,step+cnt[K-dis]);    w[++top]=make_pair(dis,step++);    for(int i=head[x];i;i=nxt[i])        if(lst[i]!=f&&!vis[lst[i]])            dfs(lst[i],x,step,dis+v[i]);}void solve(int x){    top=0,pre=1;    for(int i=head[x];i;i=nxt[i])        if(!vis[lst[i]])        {            dfs(lst[i],x,1,v[i]);            for(int j=pre;j<=top;j++)                 cnt[w[j].first]=min(cnt[w[j].first],w[j].second);            pre=top+1;        }    vis[x]=1;    for(int i=1;i<=top;i++) cnt[w[i].first]=1e9;cnt[0]=0;    for(int i=head[x];i;i=nxt[i])        if(!vis[lst[i]])        {            sum=size[lst[i]];root=0;            get_root(lst[i],0);            solve(root);        }}int main(){    mx[0]=M;    n=sc(),K=sc();    for(int i=1;i<n;i++)    {        int x=sc()+1,y=sc()+1,z=sc();        insert(x,y,z);    }    for(int i=1;i<=K;i++)cnt[i]=1e9;    ans=1e9;    sum=n,root=0;    get_root(1,0);    solve(root);    cout<<(ans>n?-1:ans);    return 0;}
0 0
原创粉丝点击