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\n",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\n",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\n",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\n",ans);
155     return 0;
156 }

 

posted @ 2018-09-19 14:22  Unstoppable728  阅读(319)  评论(0编辑  收藏  举报