zoukankan      html  css  js  c++  java
  • BZOJ 2282 & 树的直径

    SDOI2011的Dayx第2题

    题意:

      在树中找到一条权值和不超过S的链(为什么是链呢,因为题目中提到“使得路径的两端都是城市”,如果不是链那不就不止两端了吗——怎么这么机智的感觉...),使得不在链上的点与这条链的距离最大值最小。

    SOL:

      最大值最小!这不是二分的节奏么?然而hzw学长说二分更直观我却一点都没有体会到...

      这道题的关键是猜想(貌似还挺好想)并证明(貌似一直都是可有可无的东西,不过还挺好证的),路径一定在直径上,那么我们先两遍*FS找到直径,用一个队列维护链上的路径,以及预处理出直径上的点其子树中距离最远的点的距离,再维护路径两头距离直径的两端的距离即可,答案即这三者的最大值。

      总感觉应该挺快的吧但是居然比他们二分答案的慢了几倍(A得窝囊),我也就是用了一个set而已(方便取出与删除然而我觉得可以再优化不用这个set...

      关于证明:(自己口胡的证明,极其不严谨

        证明还是非常好证的(也就自己yy),我们假设一条直径,假设最优的链不在这条直径上——我们可以把这条链看作一个点,那么可以证明它的最远点一定是直径的两个端点之一(否则树的直径就可以更长),那么显然这条链是包含直径的一部分的,再证全部包含,只要在部分包含的基础上对延伸进行讨论,就得证了吧...(感觉对了就好了不过是给自己a掉多找一个正当理由...)

    CODE:

    代码实现不是很难,然而我RE几次方了把DFS改成BFS又把自带queue改成手工队列——结果小细节错误百出...

      1 /*==========================================================================
      2 # Last modified: 2016-02-12 
      3 # Filename: 2016trainning1 t1.cpp
      4 # Description: 
      5 ==========================================================================*/
      6 #define me AcrossTheSky 
      7 #include <cstdio> 
      8 #include <cmath> 
      9 #include <ctime> 
     10 #include <string> 
     11 #include <cstring> 
     12 #include <cstdlib> 
     13 #include <iostream> 
     14 #include <algorithm> 
     15    
     16 #include <set> 
     17 #include <map> 
     18 #include <stack> 
     19 #include <queue> 
     20 #include <vector> 
     21 #define lowbit(x) (x)&(-x) 
     22 #define INF 1000000000 
     23 #define FOR(i,a,b) for((i)=(a);(i)<=(b);(i)++) 
     24 #define FORP(i,a,b) for(int i=(a);i<=(b);i++) 
     25 #define FORM(i,a,b) for(int i=(a);i>=(b);i--) 
     26 #define ls(a,b) (((a)+(b)) << 1) 
     27 #define rs(a,b) (((a)+(b)) >> 1) 
     28 #define check(ch) (ch>='0'&&ch<='9')
     29 #define maxn 300001
     30 using namespace std; 
     31 typedef long long ll; 
     32 typedef unsigned long long ull; 
     33 int ans=INF;
     34 void read(int &t){
     35     int ch;
     36     for(ch=getchar( );!check(ch);ch=getchar( ));
     37     t=ch-'0';
     38     for(ch=getchar( );check(ch);ch=getchar( ))t*=10,t+=ch-'0';
     39 }
     40 /*==================split line==================*/
     41 int n,s,sume=0,maxx;
     42 struct Edge{
     43     int to,len;
     44 }e[maxn*2];
     45 struct cmp{
     46     bool operator()(const int &x,const int &y) const{
     47         return x>y;
     48     } 
     49 };
     50 int first[maxn],next[maxn*2],nextn[maxn],dis[maxn],temp[2],f[maxn],pre[maxn];
     51 int q[maxn*2];
     52 bool vis[maxn];
     53 set<int,cmp> b;
     54 void addedge(int x,int y,int len){
     55     sume++; e[sume].to=y; e[sume].len=len;
     56     next[sume]=first[x]; first[x]=sume;
     57 }
     58 void bfs(int node,int d){
     59     memset(q,0,sizeof(q));
     60     int front=1,tail=1; dis[node]=0;
     61     q[front]=node; vis[node]=true;
     62     while (front<=tail){
     63         int x=q[front];
     64         front++;
     65         if (dis[x]>maxx) maxx=dis[x],temp[d]=x;
     66         for (int i=first[x];i!=-1;i=next[i])
     67         if (!vis[e[i].to]){
     68             pre[e[i].to]=x;
     69             dis[e[i].to]=dis[x]+e[i].len;
     70             tail++; q[tail]=e[i].to; vis[e[i].to]=true;
     71         }
     72     }
     73 }
     74 void bfs1(int node,int root){
     75     memset(q,0,sizeof(q));
     76     int front=1,tail=1; q[front]=node;
     77     while (front<=tail){
     78         int x=q[front]; front++; vis[x]=true;
     79         f[root]=max(f[root],dis[x]-dis[root]);
     80         for (int i=first[x];i!=-1;i=next[i])
     81         if (e[i].to!=nextn[node] && !vis[e[i].to]){
     82             tail++; q[tail]=e[i].to;
     83         }
     84     }
     85 }
     86 int main(){
     87     read(n); read(s);
     88     FORP(i,1,n) first[i]=-1;
     89     FORP(i,1,n-1) {
     90         int x,y,l;
     91         read(x); read(y); read(l);
     92         addedge(x,y,l); addedge(y,x,l);
     93     }
     94     maxx=0; bfs(1,0);
     95     memset(vis,false,sizeof(vis));
     96     maxx=0; bfs(temp[0],1);
     97     int L=temp[1],R=temp[0];
     98     memset(vis,false,sizeof(vis));
     99     for (int i=L;i!=R;i=pre[i]) nextn[pre[i]]=i;
    100     L=temp[0],R=temp[1];
    101     for (int i=L;i!=R;i=nextn[i]) { vis[i]=true; bfs1(i,i); } 
    102     vis[R]=true; bfs1(R,R);
    103     int llen=0,rlen=maxx,head=L,tail=L,len=0;
    104      
    105     while (true){
    106         if (head==R) break;
    107         if (dis[nextn[head]]<s) {
    108             len=dis[nextn[head]];
    109             head=nextn[head];
    110             b.insert(f[head]);
    111             rlen=maxx-dis[head];
    112             continue;
    113         }
    114         break;
    115     }
    116      
    117     int t=max(rlen,max(llen,*b.begin()));
    118     if (t<ans) ans=t;
    119     while (head!=R){
    120         len=dis[nextn[head]];
    121         head=nextn[head];
    122         rlen=maxx-dis[head];
    123         while(len-dis[tail]>s){
    124             b.erase(f[tail]); tail=nextn[tail]; llen=dis[tail];
    125         }
    126         t=max(rlen,max(llen,*b.begin()));
    127         if (t<ans) ans=t;
    128     }
    129     printf("%d",ans);
    130 }
    View Code
    Sometimes it s the very people who no one imagines anything of. who do the things that no one can imagine.
  • 相关阅读:
    AngularJS ng-show 指令
    JavaScript 表单
    input type=”datetime”-local (Elements) – HTML 中文开发手册
    CSS3 overflow-y 属性
    ASP CodePage 属性
    Spring Boot的特性:外部化配置和配置随机值
    Java 之 Properties类 属性集
    Java 之 IO 异常的处理【了解】
    Java 之 字符输出流[Writer]
    Java 之 字符输入流[Reader]
  • 原文地址:https://www.cnblogs.com/YCuangWhen/p/5188165.html
Copyright © 2011-2022 走看看