zoukankan      html  css  js  c++  java
  • Bzoj2599 [IOI2011]Race

    Time Limit: 70 Sec  Memory Limit: 128 MB
    Submit: 3200  Solved: 938

    Description

    给一棵树,每条边有权.求一条简单路径,权值和等于K,且边的数量最小.N <= 200000, K <= 1000000

    Input

    第一行 两个整数 n, k
    第二..n行 每行三个整数 表示一条无向边的两端和权值 (注意点的编号从0开始)

    Output

    一个整数 表示最小边数量 如果不存在这样的路径 输出-1

    Sample Input

    4 3
    0 1 1
    1 2 2
    1 3 4

    Sample Output

    2

    HINT

     

    Source

    点分治

    人比较蠢,刚开始的写法是分治时把管辖范围内所有的点丢进一个数组,按距离排序,然后用两个指针前后夹逼……很明显是错的

    接着换成开一个数组tmp[i]记录距离根为i的点的最小深度,看上去没什么问题。然而像我在85行的注释那样写,直接从树根开始统计,就很明显是错的了(不能保证找到的两点之间路径经过根)

    接着换成了现在的写法,19s龟速AC。放弃卡常。

      1 /*by SilverN*/
      2 #include<algorithm>
      3 #include<iostream>
      4 #include<cstring>
      5 #include<cstdio>
      6 #include<cmath>
      7 #include<vector>
      8 using namespace std;
      9 const int mxn=200010;
     10 int read(){
     11     int x=0,f=1;char ch=getchar();
     12     while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
     13     while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
     14     return x*f;
     15 }
     16 struct edge{
     17     int v,nxt,w;
     18 }e[mxn<<1];
     19 int hd[mxn],mct=0;
     20 void add_edge(int u,int v,int w){
     21     e[++mct].v=v;e[mct].w=w;e[mct].nxt=hd[u];hd[u]=mct;return;
     22 }
     23 int n,k,rt;
     24 int mc[mxn],mini,sum;
     25 int tmp[1000010],cnt;
     26 int dep[mxn],dis[mxn],sz[mxn];
     27 int ans;
     28 bool vis[mxn];
     29 void DFS_sz(int u,int fa){
     30     sz[u]=1;mc[u]=0;
     31     for(int i=hd[u];i;i=e[i].nxt){
     32         int v=e[i].v;
     33         if( vis[v] || v==fa)continue;
     34         DFS_sz(v,u);
     35         sz[u]+=sz[v];
     36         mc[u]=max(mc[u],sz[v]);
     37     }
     38     mc[u]=max(mc[u],sum-sz[u]);
     39     if(mini>mc[u]){mini=mc[u];rt=u;}
     40     return;
     41 }
     42 void DFS2(int u,int fa,bool mode){
     43     if(dep[u]>ans)return;
     44     if(dis[u]<=k){
     45         if(mode)tmp[dis[u]]=min(tmp[dis[u]],dep[u]);
     46         else tmp[dis[u]]=1e8;
     47     }
     48     for(int i=hd[u];i;i=e[i].nxt){
     49         int v=e[i].v;
     50         if(vis[v] || v==fa)continue;
     51         DFS2(v,u,mode);
     52     }
     53     return;
     54 }
     55 void calc(int x,int fa){
     56     dep[x]=dep[fa]+1;
     57     if(dis[x]<=k){ans=min(ans,dep[x]+tmp[k-dis[x]]);}
     58     for(int i=hd[x];i;i=e[i].nxt){
     59         int v=e[i].v;
     60         if(vis[v] || v==fa)continue;
     61         dis[v]=dis[x]+e[i].w;
     62         calc(v,x);
     63     }
     64     return;
     65 }
     66 void solve(int x){
     67     vis[x]=1;
     68 //    dis[x]=0;
     69     tmp[0]=0;
     70 //    dep[0]=-1;
     71     dep[x]=0;
     72     for(int i=hd[x];i;i=e[i].nxt){
     73         int v=e[i].v;
     74         if(!vis[v]){
     75             dis[v]=e[i].w;
     76             calc(v,x);
     77             DFS2(v,x,1);
     78         }
     79     }    
     80     for(int i=hd[x];i;i=e[i].nxt){
     81         int v=e[i].v;
     82         if(!vis[v]){DFS2(v,x,0);}
     83     }    
     84 //    DFS2(x,0,1);
     85 //    calc(x,0);
     86 //    DFS2(x,0,0);
     87     for(int i=hd[x];i;i=e[i].nxt){
     88         int v=e[i].v;
     89         if(vis[v])continue;
     90         mini=1e8;rt=0;
     91         sum=sz[v];
     92         DFS_sz(v,0);
     93         solve(rt);
     94     }
     95     return;
     96 }
     97 int main(){
     98     int i,j,u,v,w;
     99     n=read();k=read();
    100     for(i=1;i<n;i++){
    101         u=read()+1;v=read()+1;w=read();
    102         add_edge(u,v,w);
    103         add_edge(v,u,w);
    104     }
    105     memset(tmp,0x3f,sizeof tmp);
    106     mc[rt=0]=1e8;
    107     ans=mini=1e8;
    108     sum=n;
    109     DFS_sz(1,0);
    110     solve(rt);
    111     if(ans<=n)printf("%d
    ",ans);
    112     else printf("-1
    ");
    113     return 0;
    114 }
  • 相关阅读:
    Code Review(代码的自我评审)
    在ANDROID STUDIO环境下使用Espresso 测试框架进行UI测试
    第一个迭代任务——倒计时
    Scrum的3种角色划分——倒计时
    需求分析(WBS图)
    countdown(计时器)
    Countdown(计时器)
    团队模式选择
    软件开发流程
    软件团队的模式
  • 原文地址:https://www.cnblogs.com/SilverNebula/p/6418846.html
Copyright © 2011-2022 走看看