「luogu2680」[NOIp2015] 运输计划

题目大意:给定一棵n个节点的树,输入m组一条链的两个端点;把树上的某个边权改为0,求m条链长度的最大值的最小值;

 

.考虑二分

  1.对于需要判断是否为可行方案的 mid,所有链长不大于 mid 的链不会造成影响;

  2.故只考虑链长大于 mid 的链是否可以 通过操作使它们的长度不超过mid;

  3.对于 2 显然可以得到一个充要条件 —— 存在至少一条边 被所有长度大于 mid 的链覆盖,

                      在满足上述条件的边中,至少存在一条边,其边权>=最长链的长度-mid

.问题只剩下如何处理  一.3

  边权覆盖次数——树上差分(点权下放:将一条边被覆盖的次数 (即:在差分数组中的权值) 储存在它下方的点

    如何记录?—— diff [u] ++ , diff [v]++ , diff [ lca[(u,v)] -=2;

 

代码如下:(这份代码有很多处理不当的地方,导致常数过大,如:最大链长只需处理一次,差分数组在计算时可记录 dfs 序通过一次循环处理等)

p.s. :  一个奇技淫巧:求 lca 预处理时可能会因为碰到一条链导致爆栈,这时候,不如发挥我们天马行空的想象力,因为大部分人出的链数据都是1->2->3->4……所以把 n/2+1 作为根可以防止栈溢出 (详见luoguP2680)

  1 //Author : 15owzLy1
  2 #include <iostream>
  3 #include <cstdio>
  4 #include <cstring>
  5 #include <cmath>
  6 #include <algorithm>
  7 #include <queue>
  8 #include <vector>
  9 #include <map>
 10 #include <set>
 11 #define lson tl, mid, rt<<1
 12 #define rson mid+1, tr, rt<<1|1
 13 #define pb(__) push_back(__)
 14 #define fr() front()
 15 #define bg() begin()
 16 #define it iterator
 17 #define INF 2100000000
 18 typedef long long ll;
 19 typedef double db;
 20 template<class T>inline void get_max(T &_, T __) { _=_>__?_:__; }
 21 template<class T>inline void get_min(T &_, T __) { _=_<__?_:__; }
 22 template<class T>inline void Swap(T &_, T &__) { T ___=_;_=__;__=___; }
 23 template<class T>inline T abs(T _) { return _>0?_:-_; }
 24 template<typename T>inline void read(T &_) {
 25     _=0;bool __=0;char ___=getchar();
 26     while(___<'0'||___>'9'){__|=(___=='-');___=getchar();}
 27     while(___>='0'&&___<='9'){_=(_<<1)+(_<<3)+(___^48);___=getchar();}
 28     _=__?-_:_;
 29 }
 30 
 31 const int N = 3000005;
 32 struct node {
 33     int next, to, len;
 34 }edge[N<<1];
 35 struct info {
 36     int l, r, lca;
 37 }q[N];
 38 int n, m, head[N], cnt=1, fa[N], dis[N], x, y, z, tot, rt;
 39 int dep[N], diff[N], front[N], size[N], hson[N];
 40 
 41 inline void add_Edge(int u, int v, int w) {
 42     edge[++cnt].to=v;
 43     edge[cnt].len=w;
 44     edge[cnt].next=head[u];
 45     head[u]=cnt;
 46 }
 47 
 48 //heavy-light decompostion begin
 49 void get_hson(int u) {
 50     size[u]=1;
 51     for(int i=head[u];i;i=edge[i].next) {
 52         int v=edge[i].to;
 53         if(fa[u]==v) continue;
 54         dep[v]=dep[u]+1, dis[v]=dis[u]+edge[i].len, fa[v]=u;
 55         get_hson(v);
 56         size[u]+=size[v];
 57         if(size[v]>size[hson[u]]) hson[u]=v;
 58     }
 59 }
 60 
 61 void get_front(int u, int father) {
 62     front[u]=father;
 63     if(hson[u]) get_front(hson[u], father);
 64     for(int i=head[u];i;i=edge[i].next) {
 65         int v=edge[i].to;
 66         if(fa[u]==v||hson[u]==v) continue;
 67         get_front(v, v);
 68     }
 69 }
 70 
 71 inline int lca(int u, int v) {
 72     while(front[u]!=front[v])
 73         if(dep[front[u]]>dep[front[v]]) u=fa[front[u]];
 74         else                            v=fa[front[v]];
 75     return dep[u]>dep[v]?v:u;
 76 }
 77 //heavy-light decompostion end
 78 
 79 //work begin
 80 void calc(int u, int &kk, int cnt) {
 81     for(int i=head[u];i;i=edge[i].next) {
 82         int v=edge[i].to, w=edge[i].len;
 83         if(v==fa[u]) continue;
 84         calc(v, kk, cnt);
 85         if(diff[v]>=cnt) get_max(kk, w);
 86         diff[u]+=diff[v];
 87     }
 88 }
 89 
 90 inline int check(int lim) {
 91     int max=0, cnt=0, max_edge=0;
 92     memset(diff, 0, sizeof(diff));
 93     for(int i=1;i<=m;i++)
 94         if(dis[q[i].l]+dis[q[i].r]-2*dis[q[i].lca]>lim) {
 95             ++cnt;
 96             diff[q[i].l]++, diff[q[i].r]++, diff[q[i].lca]-=2;
 97             get_max(max, dis[q[i].l]+dis[q[i].r]-2*dis[q[i].lca]);
 98         }
 99     calc(rt, max_edge, cnt);
100     if(max-max_edge>lim)
101         return false;
102     return true;
103 }
104 
105 inline int Binary_Search(int l, int r) {
106     int ret=r, mid;
107     while(l<=r) {
108         mid=l+r>>1;
109         if(check(mid)) ret=mid, r=mid-1;
110         else           l=mid+1;
111     }
112     return ret;
113 }
114 //work end
115 
116 int main() {
117     freopen("transport.in","r",stdin);
118     freopen("transport.out","w",stdout);
119     int max=0;
120     read(n), read(m);
121     for(int i=1;i<n;i++) {
122         read(x), read(y), read(z);
123         add_Edge(x, y, z), add_Edge(y, x, z);
124     }
125     rt=(n>>1)+1;
126     dep[rt]=1; get_hson(rt); get_front(rt, rt);
127     for(int i=1;i<=m;i++) {
128         read(q[i].l), read(q[i].r);
129         q[i].lca=lca(q[i].l, q[i].r);
130         get_max(max, dis[q[i].l]+dis[q[i].r]-2*dis[q[i].lca]);
131     }
132     printf("%d\n", Binary_Search(0, max));
133     fclose(stdin);
134     fclose(stdout);
135     return 0;
136 } 
View Code

 

posted @ 2018-11-01 16:12  15owzLy1  阅读(141)  评论(0编辑  收藏  举报