• loj2425 「NOIP2015」运输计划[二分答案+树上差分]


    看到题意最小化最长路径,显然二分答案,枚举链长度不超过$ ext{mid}$,然后尝试检验。`````

    检验是否存在这样一个边置为0后,全部链长$le ext{mid}$,其最终目标就是、要让所有$> ext{mid}$的链长通过找出一个为0的公共边减掉而全部变为$le ext{mid}$的

    那么,统计出这$tot$条超出$ ext{mid}$的链的路径上覆盖的边,一条被覆盖了$tot$次的边就可能具备条件,于是贪心找最大的满足条件的边,看是否可以把所有链(也就是最长链)搞成$le ext{mid}$的,$O(n)$树上差分即可。

    于是$O(n ext{log}len)$。

    准备去(gu)学(gu)习(gu)的做法:据说当年考场这题log是被卡掉一两个点的?所以有线性做法?待补

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<cmath>
     6 #define dbg(x) cerr << #x << " = " << x <<endl
     7 using namespace std;
     8 typedef long long ll;
     9 typedef double db;
    10 typedef pair<int,int> pii;
    11 template<typename T>inline T _min(T A,T B){return A<B?A:B;}
    12 template<typename T>inline T _max(T A,T B){return A>B?A:B;}
    13 template<typename T>inline char MIN(T&A,T B){return A>B?(A=B,1):0;}
    14 template<typename T>inline char MAX(T&A,T B){return A<B?(A=B,1):0;}
    15 template<typename T>inline void _swap(T&A,T&B){A^=B^=A^=B;}
    16 template<typename T>inline T read(T&x){
    17     x=0;int f=0;char c;while(!isdigit(c=getchar()))if(c=='-')f=1;
    18     while(isdigit(c))x=x*10+(c&15),c=getchar();return f?x=-x:x;
    19 }
    20 const int N=3e5+7;
    21 struct thxorz{int to,nxt,w;}G[N<<1];
    22 struct stothx{int to,nxt,id;}Q[N<<1];
    23 struct query{int x,y,lca,dis;}q[N];
    24 int Head[N],tot=1,qh[N],qt;
    25 int n,m,L,R,maxdis,maxe;
    26 inline void Addedge(int x,int y,int z){
    27     G[++tot].to=y,G[tot].nxt=Head[x],Head[x]=tot,G[tot].w=z;
    28     G[++tot].to=x,G[tot].nxt=Head[y],Head[y]=tot,G[tot].w=z;
    29 }
    30 inline void AddQuery(int x,int y,int id){
    31     Q[++qt].to=y,Q[qt].nxt=qh[x],qh[x]=qt,Q[qt].id=id;
    32     Q[++qt].to=x,Q[qt].nxt=qh[y],qh[y]=qt,Q[qt].id=id;
    33 }
    34 #define y G[j].to
    35 #define qy Q[j].to
    36 int vis[N],anc[N],dep[N];
    37 int get_anc(int x){return x==anc[x]?x:anc[x]=get_anc(anc[x]);}
    38 void tarjan(int x,int fa){
    39     anc[x]=x;
    40     for(register int j=Head[x];j;j=G[j].nxt)if(y^fa)dep[y]=dep[x]+G[j].w,tarjan(y,x),anc[y]=x;
    41     vis[x]=1;
    42     for(register int j=qh[x];j;j=Q[j].nxt)if(vis[qy])
    43         q[Q[j].id].lca=get_anc(qy),q[Q[j].id].dis=dep[x]+dep[qy]-(dep[q[Q[j].id].lca]<<1),MAX(R,q[Q[j].id].dis);
    44 }
    45 int d[N],del,cnt;
    46 int dfs(int x,int c){
    47     int ret=d[x];
    48     for(register int j=Head[x];j;j=G[j].nxt)if(y^G[c^1].to)ret+=dfs(y,j);
    49     if(ret==cnt)MAX(del,G[c].w);
    50     return ret;
    51 }
    52 #undef y
    53 #undef qy
    54 inline int check(int mid){
    55     memset(d,0,sizeof d),del=cnt=0;
    56     for(register int i=1;i<=m;++i)if(q[i].dis>mid)++d[q[i].x],++d[q[i].y],d[q[i].lca]-=2,++cnt;
    57     dfs(1,0);
    58     return maxdis-del<=mid;
    59 }
    60 int main(){//freopen("test.in","r",stdin);freopen("test.ans","w",stdout);
    61     read(n),read(m);
    62     for(register int i=1,x,y,z;i<n;++i)read(x),read(y),read(z),Addedge(x,y,z),MAX(L,z);
    63     for(register int i=1;i<=m;++i)read(q[i].x),read(q[i].y),AddQuery(q[i].x,q[i].y,i);
    64     tarjan(1,0);maxdis=R,maxe=L;L=R-L;//dbg(maxdis),dbg(maxe);
    65     while(L<R){
    66         int mid=L+R>>1;
    67         if(check(mid))R=mid;
    68         else L=mid+1;
    69     }
    70     printf("%d
    ",L);
    71     return 0;
    72 }
    View Code

    总结反思:瓶颈在check。关键在于要放眼全部,不要都放在maxdis上;求边若干次覆盖的统计可以往树上差分上想。

  • 相关阅读:
    校外实习-7.28
    校外实习-7.27
    校外实习-7.26
    校外实习-7.25
    校外实习-第三周总结
    校外实习-7.22
    校外实习-7.21
    校外实习-7.20
    作业九—总结
    结对编程项目---四则运算(截图总结篇)
  • 原文地址:https://www.cnblogs.com/saigyouji-yuyuko/p/11587424.html
走看看 - 开发者的网上家园