zoukankan      html  css  js  c++  java
  • bzoj2067: [Poi2004]SZN

    bzoj2067: [Poi2004]SZN

    一开始没看出来是贪心,还以为是树规,多亏ooo提醒一句,然后刚了一个半小时搞出来了。

    首先‘最长线最短’二分没错了,想了想他确实是单调的,最长线越长,用的线就越短(注意这里的最长线只是不超过,并不是一定要达到)。

    二分最长线长度,对于已知的最长线长度len,考虑如何求解最少线数。

    树里有什么特殊的点吗?叶子节点,叶子节点一定是一条线的一个端点。所以从叶子节点开始,一条线最优肯定是直接连接两个叶子节点,证明自己YY(其实是我不会)。

    设f[i]表示节点i向上的线的长度。显然叶子节点的f为1。对于非叶子节点考虑如何合并:

    f相加<=len的两个儿子可以合并,但并不是随便合并就是最优的。可以将儿子存到一个队列里,按f值从小到大排序,用两个指针实现合并。如果f[head]+f[tail]<=len直接合并head++,tail--,ans++。如果大于len直接把tail独立成一条线吗?这样并不是最优的,可以把tail的值记录加到f[x]到上一层合并。但是只能有一个点和x接上,显然选f最小的,其他的点就只能独立成一条线了。注意最后如果head==tail要特判是和x接上还是独立成一条线

    这样直接合并到根就求出了最长线长度为len时的最少线数。

    复杂度我不会算,有点玄但是跑的还挺快。

      1 //19.00~20.00 :93
      2 //20.00~20.25 :100
      3 #include<algorithm>
      4 #include<iostream>
      5 #include<cstring>
      6 #include<cstdio>
      7 #define int LL
      8 #define MAXN 20010
      9 #define LL long long
     10 #define ma(x) memset(x,0,sizeof(x))
     11 using namespace std;
     12 struct edge
     13 {    
     14     int u,v,nxt;
     15     #define u(x) ed[x].u
     16     #define v(x) ed[x].v
     17     #define n(x) ed[x].nxt
     18 }ed[MAXN*4];
     19 int first[MAXN],num_e;
     20 #define f(x) first[x]
     21 const int INF=0x7ffffffffff;
     22 int n,tans;
     23 int f[MAXN];
     24 
     25 pair<int,int> q[MAXN];int head,tail;
     26 void dfs(int x,int fa,int len)
     27 {
     28     int tem=0;
     29     for(int i=f(x);i;i=n(i))
     30     if(v(i)!=fa){dfs(v(i),x,len);}
     31     
     32     f[x]=0;if(x!=1)f[x]++;head=1,tail=0;int ooo=INF;
     33     for(int i=f(x);i;i=n(i))
     34     if(v(i)!=fa)
     35         if(f[v(i)]==len)tans++;
     36         else{q[++tail]=make_pair(f[v(i)],v(i));}
     37     sort(q+head,q+tail+1);
     38     while(head<tail)
     39     {
     40         if(q[head].first+q[tail].first>len)
     41         {
     42             if(q[tail].first<ooo)
     43             {
     44                 if(ooo!=INF)tans++;
     45                 ooo=q[tail].first;tail--;
     46             }
     47             else tans++,tail--;
     48         }
     49         else head++,tail--,tans++;
     50     }
     51     if(head==tail)
     52     {
     53         if(q[tail].first<ooo)
     54         {
     55             if(ooo!=INF)tans++;
     56             ooo=q[tail].first;
     57         }
     58         else tans++;
     59     }
     60     if(ooo!=INF)f[x]+=ooo;
     61 }
     62 int solve(int len)
     63 {
     64     ma(f);tans=0;    
     65     dfs(1,0,len);
     66     if(f[1])tans++;
     67     return tans;
     68 }    
     69 inline int read();
     70 inline void add(int u,int v);
     71 signed main()
     72 {    
     73 //    freopen("in.txt","r",stdin);    
     74     //freopen("1.out","w",stdout);
     75 
     76     n=read();int ta,tb;
     77     for(int i=1;i<n;i++)
     78         ta=read(),tb=read(),
     79         add(ta,tb),add(tb,ta);
     80     int l=1,r=n,mid,ans=solve(n),now=INF;
     81     int ans1,ans2;
     82     while(l<=r)
     83     {
     84         mid=(l+r)>>1;    
     85         int res=solve(mid);    
     86         if(res>ans)l=mid+1;
     87         else 
     88         {
     89             r=mid-1,ans=res;
     90             ans1=mid;ans2=res;
     91         }
     92     }
     93     printf("%lld %lld
    ",ans2,ans1);
     94 }
     95 inline int read()
     96 {    
     97     int s=0,f=1;char a=getchar();
     98     while(a<'0'||a>'9'){if(a=='-')f=-1;a=getchar();}
     99     while(a>='0'&&a<='9'){s=s*10+a-'0';a=getchar();}
    100     return s*f;
    101 }
    102 inline void add(int u,int v)
    103 {    
    104     ++num_e;
    105     u(num_e)=u;
    106     v(num_e)=v;
    107     n(num_e)=f(u);
    108     f(u)=num_e;
    109 }
    View Code
  • 相关阅读:
    python--向钉钉群发送消息(亲测可用)
    python--注册钉钉回调事件(亲测可用)
    Gradle
    SpringBoot 中thymeleaf模板引擎的使用
    SpringBoot对静态资源的映射规则
    SpringBoot的日志使用
    rsync实现文件同步
    python学习: 优秀Python学习资源收集汇总--转
    Python高级特性: 12步轻松搞定Python装饰器
    Python常见问题
  • 原文地址:https://www.cnblogs.com/Al-Ca/p/11336869.html
Copyright © 2011-2022 走看看