zoukankan      html  css  js  c++  java
  • NOIP2015运输计划(二分答案)

    题目描述

    公元2044年,人类进入了宇宙纪元。

    L国有n个星球,还有n-1条双向航道,每条航道建立在两个星球之间,这n-1条航道连通了L国的所有星球。

    小P掌管一家物流公司,该公司有很多个运输计划,每个运输计划形如:有一艘物流飞船需要从ui号星球沿最快的宇航路径飞行到vi号星球去。显然,飞船驶过一条航道是需要时间的,对于航道j,任意飞船驶过它所花费的时间为tj,并且任意两艘飞船之间不会产生任何干扰。

    为了鼓励科技创新,L国国王同意小P的物流公司参与L国的航道建设,即允许小P把某一条航道改造成虫洞,飞船驶过虫洞不消耗时间。

    在虫洞的建设完成前小P的物流公司就预接了m个运输计划。在虫洞建设完成后,这m个运输计划会同时开始,所有飞船一起出发。当这m个运输计划都完成时,小P的物流公司的阶段性工作就完成了。

    如果小P可以自由选择将哪一条航道改造成虫洞,试求出小P的物流公司完成阶段性工作所需要的最短时间是多少?

    输入格式

    第一行包括两个正整数n、m,表示L国中星球的数量及小P公司预接的运输计划的数量,星球从1到n编号。

    接下来n-1行描述航道的建设情况,其中第i行包含三个整数ai, bi和ti,表示第i条双向航道修建在ai与bi两个星球之间,任意飞船驶过它所花费的时间为ti。

    接下来m行描述运输计划的情况,其中第j行包含两个正整数uj和vj,表示第j个运输计划是从uj号星球飞往vj号星球。

    输出格式

    共1行,包含1个整数,表示小P的物流公司完成阶段性工作所需要的最短时间。

    input

    6 3
    1 2 3
    1 6 4
    3 1 7
    4 3 6
    3 5 5
    3 6
    2 5
    4 5
    

    output

    11
    

    样例说明

    将第1条航道改造成虫洞:则三个计划耗时分别为:11、12、11,故需要花费的时间为12。

    将第2条航道改造成虫洞:则三个计划耗时分别为:7、15、11,故需要花费的时间为15。

    将第3条航道改造成虫洞:则三个计划耗时分别为:4、8、11,故需要花费的时间为11。

    将第4条航道改造成虫洞:则三个计划耗时分别为:11、15、5,故需要花费的时间为15。

    将第5条航道改造成虫洞:则三个计划耗时分别为:11、10、6,故需要花费的时间为11。

    故将第3条或第5条航道改造成虫洞均可使得完成阶段性工作的耗时最短,需要花费的时间为11。

    限制与约定

    解题思路:

    首先考虑一下暴力,在n,m都小于3000时,先将两点间的边权值转化为深度较大的点的权值,利用朴素LCA求出两点间的耗费时间,再枚举删去哪一点枚举m中答案,更新即可

    时间复杂度O(n*m),期望得分60分

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 using namespace std;
      5 typedef long long lnt;
      6 struct pnt{
      7     int hd;
      8     int no;
      9     int fa;
     10     int ol;
     11     int dp;
     12     lnt val;
     13 }p[1000000];
     14 struct ent{
     15     int twd;
     16     int lst;
     17     lnt tim;
     18 }e[1000000];
     19 int cnt;
     20 int n,m;
     21 lnt ans=0x7f7f7f7f7f7f7f7fll;
     22 int u[300001];
     23 int v[300001];
     24 int tf[300001];
     25 int hv[3005][3005];
     26 void ade(int f,int t,lnt y)
     27 {
     28     cnt++;
     29     e[cnt].twd=t;
     30     e[cnt].lst=p[f].hd;
     31     p[f].hd=cnt;
     32     e[cnt].tim=y;
     33 }
     34 void dfs(int x,int f)
     35 {
     36     p[x].dp=p[f].dp+1;
     37     p[x].fa=f;
     38     for(int i=p[x].hd;i;i=e[i].lst)
     39     {
     40         int to=e[i].twd;
     41         if(to!=f)
     42         {
     43             p[to].val=e[i].tim;
     44             dfs(to,x);
     45         }
     46     }
     47     return ;
     48 }
     49 int main()
     50 {
     51     scanf("%d%d",&n,&m);
     52     for(int i=1;i<n;i++)
     53     {
     54         int a,b;
     55         lnt c;
     56         scanf("%d%d%lld",&a,&b,&c);
     57         ade(a,b,c);
     58         ade(b,a,c);
     59     }
     60     dfs(1,1);
     61     for(int i=1;i<=m;i++)
     62     {
     63         scanf("%d%d",&u[i],&v[i]);
     64     }
     65     if(m==1)
     66     {
     67         lnt mtmp=0;
     68         lnt mins=0;
     69         int x=u[1];
     70         int y=v[1];
     71         if(p[x].dp<p[y].dp)
     72             swap(x,y);
     73         while(p[x].dp!=p[y].dp)
     74         {
     75             mtmp+=p[x].val;
     76             mins=max(mins,p[x].val);
     77             x=p[x].fa;
     78         }
     79         if(x==y)
     80         {
     81             printf("%lld
    ",mtmp-mins);
     82             return 0;
     83         }
     84         while(x!=y)
     85         {
     86             mins=max(mins,p[x].val);
     87             mins=max(mins,p[y].val);
     88             mtmp+=p[x].val;
     89             x=p[x].fa;
     90             mtmp+=p[y].val;
     91             y=p[y].fa;
     92         }
     93         printf("%lld
    ",mtmp-mins);
     94         return 0;
     95     }
     96     for(int i=1;i<=m;i++)
     97     {
     98         lnt mtmp=0;
     99         int x=u[i];
    100         int y=v[i];
    101         if(p[x].dp<p[y].dp)
    102             swap(x,y);
    103         while(p[x].dp!=p[y].dp)
    104         {
    105             hv[i][x]=1;
    106             mtmp+=p[x].val;
    107             x=p[x].fa;
    108         }
    109         if(x==y)
    110         {
    111             tf[i]=mtmp;
    112             continue;
    113         }
    114         while(x!=y)
    115         {
    116             hv[i][x]=1;
    117             hv[i][y]=1;
    118             mtmp+=p[x].val;
    119             x=p[x].fa;
    120             mtmp+=p[y].val;
    121             y=p[y].fa;
    122         }
    123         tf[i]=mtmp;
    124     }
    125     for(int i=2;i<=n;i++)
    126     {
    127         lnt maxs=0;
    128         for(int j=1;j<=m;j++)
    129         {
    130             maxs=max(maxs,tf[j]-(lnt)hv[j][i]*p[i].val);
    131         }
    132         ans=min(ans,maxs);
    133     }
    134     printf("%lld
    ",ans);
    135     return 0;
    136 }

     正解:

    二分答案+树上打差分

    将计划排序。

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 using namespace std;
      5 typedef long long lnt;
      6 struct pnt{
      7     int fa;
      8     int dp;
      9     int hd;
     10     int ola;
     11     int sgrl;
     12     lnt dis;
     13 }p[1000000];
     14 struct ent{
     15     int twd;
     16     int lst;
     17     lnt vls;
     18 }e[1000000];
     19 struct qnt{
     20     int u;
     21     int v;
     22     lnt dtc;
     23 }q[10000000];
     24 int n,m;
     25 int cnt;
     26 int ont;
     27 int lsd;
     28 int top;
     29 int old[20][1000000];
     30 int lg[2000000];
     31 int lns[2000000];
     32 int lfs[2000000];
     33 bool cmp(qnt x,qnt y)
     34 {
     35     return x.dtc>y.dtc;
     36 }
     37 void ade(int f,int t,lnt v)
     38 {
     39     cnt++;
     40     e[cnt].twd=t;
     41     e[cnt].lst=p[f].hd;
     42     e[cnt].vls=v;
     43     p[f].hd=cnt;
     44 }
     45 void dfs_build(int x,int f)
     46 {
     47     old[0][++ont]=x;
     48     p[x].fa=f;
     49     p[x].dp=p[f].dp+1;
     50     p[x].ola=ont;
     51     bool flag=1;
     52     for(int i=p[x].hd;i;i=e[i].lst)
     53     {
     54         int to=e[i].twd;
     55         if(to!=f)
     56         {
     57             flag=false;
     58             p[to].dis=p[x].dis+e[i].vls;
     59             dfs_build(to,x);
     60             old[0][++ont]=x;
     61         }
     62     }
     63     if(flag)
     64     {
     65         lfs[++lsd]=x;
     66     }
     67 }
     68 void Tr_dfs(int x,int f)
     69 {
     70     for(int i=p[x].hd;i;i=e[i].lst)
     71     {
     72         int to=e[i].twd;
     73         if(to!=f)
     74         {
     75             Tr_dfs(to,x);
     76             p[x].sgrl+=p[to].sgrl;
     77         }
     78     }
     79     return ;
     80 }
     81 int rmaxs(int x,int y)
     82 {
     83     return p[x].dp>p[y].dp?y:x;
     84 }
     85 int lca(int x,int y)
     86 {
     87     if(p[x].ola>p[y].ola)
     88         swap(x,y);
     89     int lgg=lg[p[y].ola-p[x].ola+1];
     90     return rmaxs(old[lgg][p[x].ola],old[lgg][p[y].ola-(1<<lgg)+1]);
     91 }
     92 int Ccl(int agc)
     93 {
     94     int x=0;
     95     while(agc<q[x+1].dtc)x++;
     96     if(lns[x])return lns[x];
     97     for(int i=1;i<=n;i++)
     98         p[i].sgrl=0;
     99     for(int i=1;i<=x;i++)
    100     {
    101         p[q[i].u].sgrl++;
    102         p[q[i].v].sgrl++;
    103         p[lca(q[i].v,q[i].u)].sgrl-=2;
    104     }
    105     Tr_dfs(1,1);
    106     lnt ans=0;
    107     for(int i=1;i<=n;i++)
    108     {
    109         if(p[i].sgrl==x)
    110         {
    111             ans=max(ans,p[i].dis-p[p[i].fa].dis);
    112         }
    113     }
    114     lns[x]=ans;
    115     return ans;
    116 }
    117 int main()
    118 {
    119     scanf("%d%d",&n,&m);
    120     for(int i=1;i<n;i++)
    121     {
    122         int x,y;
    123         int z;
    124         scanf("%d%d%d",&x,&y,&z);
    125         ade(x,y,z);
    126         ade(y,x,z);
    127     }
    128     for(int i=2;i<=3*n;i++)
    129     {
    130         lg[i]=lg[i/2]+1;
    131     }
    132     dfs_build(1,1);
    133     for(int i=1;i<=20;i++)
    134         for(int j=1;j+(1<<i)-1<=ont;j++)
    135             old[i][j]=rmaxs(old[i-1][j],old[i-1][j+(1<<i-1)]);
    136     for(int i=1;i<=m;i++)
    137     {
    138         scanf("%d%d",&q[i].u,&q[i].v);
    139         q[i].dtc=p[q[i].u].dis+p[q[i].v].dis-2*p[lca(q[i].v,q[i].u)].dis;
    140     }
    141     sort(q+1,q+m+1,cmp);
    142     int l=0;
    143     int r=q[1].dtc;
    144     int ans;
    145     while(l<=r)
    146     {
    147         int mid=(l+r)>>1;
    148         if(q[1].dtc-Ccl(mid)>mid)l=mid+1;
    149         else{
    150             ans=mid;
    151             r=mid-1;
    152         }
    153     }
    154     printf("%d
    ",ans);
    155     return 0;
    156 }
  • 相关阅读:
    java(一) 基础部分
    Spring使用Autowiring自动装配 解决提示报错小技巧
    idea 中dao层自动生成接口
    从git远程仓库Checkout项目到本地
    idea 新建项目上传至git(coding)
    使用Travis CI给hexo部署做持续集成
    LeetCode395-至少有 K 个重复字符的最长子串
    Java注解
    Java反射
    Java反射应用实例
  • 原文地址:https://www.cnblogs.com/blog-Dr-J/p/9498535.html
Copyright © 2011-2022 走看看