zoukankan      html  css  js  c++  java
  • IOI2011 Race 点分治

    题意:

      给一棵树,每条边有权。求一条简单路径,权值和等于K,且边的数量最小。

    分析:

      对于这道题,和计算长度恰好为k的路径数量差不多,只不过那个所谓的桶里不装数量,装达到这个长度的最小的边数。

      (感觉把这个桶应用好,能解决点分治的不少题目)

      当然呢,为了进一步节约时间,我们不必每次都把桶memset一次,只需要把用过的位置都记录下来,用完后还原即可。

      这里有两种实现方法,一个较长一个较短,一个稍快一个稍慢。

      其实这个题还有一种做法,就是树上启发式合并(不过我并没有去写)一道好题目本来就是很多种思路的火种,建议大家用不同的方法实现这道题。

    代码:

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 #include<algorithm>
     5 #include<cmath>
     6 #define ll long long
     7 using namespace std;
     8 const int N=200005;int rt,sum;
     9 struct node{int y,z,nxt;}edge[N*2];
    10 int n,k,head[N],cn=0,siz[N],son[N];
    11 void add(int x,int y,int z){
    12     edge[++cn]=(node){y,z,head[x]};head[x]=cn;
    13     edge[++cn]=(node){x,z,head[y]};head[y]=cn;
    14 } bool vis[N];
    15 void getrt(int x,int fa){
    16     siz[x]=1;son[x]=0;
    17     for(int i=head[x],y;~i;i=edge[i].nxt){
    18         if((y=edge[i].y)==fa||vis[y])continue;
    19         getrt(y,x);siz[x]+=siz[y];
    20         if(son[x]<siz[y]) son[x]=siz[y];
    21     } son[x]=max(son[x],sum-siz[x]);
    22     if(son[x]<son[rt]) rt=x;
    23 } int tmp[N*10],ans=1e9;
    24 void dfs(int x,int fa,int d,int cnt){
    25     if(d>k) return ;
    26     ans=min(ans,tmp[k-d]+cnt);
    27     for(int i=head[x],y;~i;i=edge[i].nxt){
    28         y=edge[i].y;if(y==fa||vis[y])continue;
    29         dfs(y,x,d+edge[i].z,cnt+1);
    30     } return ;
    31 }
    32 void update(int x,int fa,int d,int cnt){
    33     if(d>k) return ;
    34     tmp[d]=min(tmp[d],cnt);
    35     for(int i=head[x],y;~i;i=edge[i].nxt){
    36         y=edge[i].y;if(y==fa||vis[y])continue;
    37         update(y,x,d+edge[i].z,cnt+1);
    38     } return ;
    39 }
    40 void clear(int x,int fa,int d){
    41     if(d>k) return ;tmp[d]=1e9;
    42     for(int i=head[x],y;~i;i=edge[i].nxt){
    43         y=edge[i].y;if(y==fa||vis[y])continue;
    44         clear(y,x,d+edge[i].z);
    45     }return ;
    46 }
    47 void solve(int x,int sz){
    48     tmp[0]=0;vis[x]=1;
    49     for(int i=head[x],y;~i;i=edge[i].nxt){
    50         if(vis[y=edge[i].y]) continue;
    51         dfs(y,x,edge[i].z,1);
    52         update(y,x,edge[i].z,1);
    53     } clear(x,0,0);
    54     for(int i=head[x],y;~i;i=edge[i].nxt){
    55         if(vis[y=edge[i].y]) continue;
    56         sum=(siz[y]>siz[x]?sz-siz[x]:siz[y]);
    57         rt=0;son[0]=sum;getrt(y,0);
    58         solve(rt,sum);
    59     } return ;
    60 }
    61 int main(){
    62     memset(head,-1,sizeof(head));
    63     scanf("%d%d",&n,&k);int t1,t2,t3;
    64     for(int i=1;i<n;i++){
    65         scanf("%d%d%d",&t1,&t2,&t3);
    66         add(t1+1,t2+1,t3);
    67     } for(int i=0;i<=k;i++) tmp[i]=1e9;
    68     sum=n;rt=0;son[0]=n;
    69     getrt(1,0);solve(rt,n);
    70     if(ans!=1e9) printf("%d
    ",ans);
    71     else puts("-1");return 0;
    72 }
    点分治
     1 #include<bits/stdc++.h>
     2 #define ll long long
     3 using namespace std;
     4 const int N=2000005,M=1000005;
     5 struct link{int l,d;}q[N];
     6 int h[N],n,m,k,mx[N],dis[N];
     7 ll t[M],ans=0;int sm,tmp[N];
     8 struct node{int y,z,nxt;}e[N*2];
     9 int d[N],rt,vis[N],siz[N],c=1,cnt=0;
    10 void add(int x,int y,int z){
    11     e[++c]=(node){y,z,h[x]};h[x]=c;
    12     e[++c]=(node){x,z,h[y]};h[y]=c;
    13 } void getrt(int x,int fa){
    14     siz[x]=1;mx[x]=0;
    15     for(int i=h[x],y;i;i=e[i].nxt)
    16     if((y=e[i].y)!=fa&&!vis[y])
    17     getrt(y,x),siz[x]+=siz[y],
    18     mx[x]=max(mx[x],siz[y]);
    19     mx[x]=max(mx[x],sm-siz[x]);
    20     if(mx[x]<mx[rt]) rt=x;return ;
    21 } void dfs(int x,int fa){
    22     q[++cnt]=(link){d[x],dis[x]};
    23     for(int i=h[x],y;i;i=e[i].nxt)
    24     if((y=e[i].y)!=fa&&!vis[y])
    25     d[y]=d[x]+e[i].z,dis[y]=dis[x]+1,
    26     dfs(y,x);return ;
    27 } void calc(int x){ tmp[0]=0;
    28     for(int i=h[x],y;i;i=e[i].nxt)
    29     if(!vis[y=e[i].y]){
    30         cnt=0;d[y]=e[i].z;dis[y]=1;dfs(y,x);
    31         for(int j=cnt;j;j--)
    32         if(q[j].l<=k) ans=
    33         min(t[k-q[j].l]+q[j].d,ans);
    34         for(int j=cnt;j;j--)
    35         if(q[j].l<=k) t[q[j].l]=
    36         min(t[q[j].l],q[j].d*1ll),
    37         tmp[++tmp[0]]=q[j].l;
    38     } for(int i=tmp[0];i;i--) t[tmp[i]]=2e9;
    39 } void solve(int x){
    40     vis[x]=1;t[0]=0;calc(x);
    41     for(int i=h[x],y;i;i=e[i].nxt)
    42     if(!vis[y=e[i].y]){
    43         sm=siz[y];mx[rt=0]=N;
    44         getrt(y,0);solve(rt);
    45     } return ;
    46 } int main(){
    47     scanf("%d%d",&n,&k);ans=2e9;
    48     memset(t,0x3f,sizeof(t));
    49     for(int i=1,x,y,z;i<n;i++)
    50     scanf("%d%d%d",&x,&y,&z),
    51     add(x+1,y+1,z);mx[rt]=sm=n;
    52     getrt(1,0);solve(rt);
    53     if(ans>=1e9) puts("-1");else
    54     printf("%lld
    ",ans);return 0;
    55 }
    点分治(较短)
  • 相关阅读:
    解决一起web 页面被劫持的案例
    django rest framwork教程之外键关系和超链接
    django restframwork 教程之authentication权限
    Puppet nginx+passenger模式配置
    Django restframwork教程之类视图(class-based views)
    使用emplace操作
    C++中的显示类型转换
    整数加法
    在不知道学生人数和每个学生课程数量的情况下对学生的平均成绩排序
    树的高度
  • 原文地址:https://www.cnblogs.com/Alan-Luo/p/10424317.html
Copyright © 2011-2022 走看看