BZOJ 1517 [POI2006]Met

来源:互联网 发布:阿里巴巴斑马网络 编辑:程序博客网 时间:2024/06/06 10:54

title: ‘BZOJ 1517 [POI2006]Met’
categories: BZOJ
date: 2015-10-21 16:54:00
tags: [贪心,拓扑排序]


Description

给出一棵N个结点的树,选择L条路径,覆盖这些路径上的结点,使得被覆盖到的结点数最多。

Input

第一行两个正整数N、L(2 <= N <= 1,000,000, 0 <= L <= N)。下面有N-1行,每行两个正整数A和B(1 <= A, B <= N),表示一条边(A,B)。

Output

一个整数,表示最多能覆盖到多少结点。

Sample

input.txt
17 3
1 2
3 2
2 4
5 2
5 6
5 8
7 8
9 8
5 10
10 13
13 14
10 12
12 11
15 17
15 16
15 10

output.txt
13

Solution

(试一试刚学到的爆炸读入优化,2333333)
一开始想乱贪,找什么树的直径,然而复杂度挺爆炸的,正确性也不能证明。
于是只能看了一发题解,发现人家说:选择路径的代价相同显然考虑贪心。
很有道理的样子。
我们发现每条路径一定是从一个叶子节点(度为1的节点)到另一个叶子节点,于是叶子节点这一层上面一定会选l对节点,即2*l个节点,而叶子节点上又一定能拓展往它的上一层,于是我们发现,每一层都能选出min(2l,sum[dep])个节点被覆盖。等等,这个层是按什么分的层?没错,是按拓扑关系来分层。于是算法就能很愉快地出来了,累加出每一层对答案的贡献min(2l,sum[dep])即可。
然而我发现以前自己拓扑都是用栈打的,所以分出的层不均匀,WA了几万年。什么叫分出的层不均匀?比如在1-2-3-4这条链上,它们的层数会被划分成:1,2,3,1;然而正确的层数应该是:1,2,2,1。于是我们把栈改用队列就可以了,看来以后还是要提高一下自己的姿势水平。

Code

#include<stack>#include<queue>#include<cstdio>#include<cstdarg>#include<cstdlib>#include<cstring>#include<iostream>#include<algorithm>#ifdef __GNUC__#include<unistd.h>#endif#define maxn 1000000+5using namespace std;//#define UsingIOExceptionstatic class Scanner{    typedef double D;    typedef unsigned int long II;    typedef signed int long SI;    typedef unsigned char S;    typedef char C;    typedef bool B;    static II const ScL =16384,Eof =0xff;#ifdef __GNUC__    II const buffer;#else    FILE *const buffer;#endif    S ram[ScL],*begin,*end;public:#ifdef UsingIOException    enum IOException    {        FileEof,TypeError    };#endif#ifdef __GNUC__#ifdef Fin    Scanner(II const iobuffer=open(Fin,1)):buffer(iobuffer),begin(ram),end(ram)#else    Scanner(II const iobuffer=0):buffer(iobuffer),begin(ram),end(ram)#endif#else#ifdef Fin    Scanner(FILE *const iobuffer=fopen(Fin,"rb")):buffer(iobuffer),begin(ram),end(ram)#else    Scanner(FILE *const iobuffer=stdin):buffer(iobuffer),begin(ram),end(ram)#endif#endif    {    }    ~Scanner(void)    {#ifdef __GNUC__        close(buffer);#else        fclose(buffer);#endif    }    II get(void)    {        if(begin==end)        {            begin=ram;#ifdef __GNUC__            if((end=(begin=ram)+read(buffer,ram,ScL))==ram)#else            if((end=(begin=ram)+fread(ram,1,ScL,buffer))==ram)#endif                return Eof;        }        return *begin++;    }    D getSD(void)    {        II j;        while(isspace(j=get()));        B neg=false;        if(j=='-')        {            neg=true;            j=get();        }#ifdef UsingIOException        if(!isdigit(j))            throw j==Eof?FileEof:TypeError;#endif        SI i=j-'0';        while(isdigit(j=get()))            i=(i<<3)+(i<<1)+(j-'0');        if(j=='.')        {            D val=D(i),level=1.;            while(isdigit(j=get()))                val+=(level*=.1)*D(j-'0');            return neg?-val:val;        }        return neg?-i:i;    }    D getD(void)    {        II j;        while(isspace(j=get()));#ifdef UsingIOException        if(!isdigit(j))            throw j==Eof?FileEof:TypeError;#endif        II i=j-'0';        while(isdigit(j=get()))            i=(i<<3)+(i<<1)+(j-'0');        if(j=='.')        {            D val=D(i),level=1.;            while(isdigit(j=get()))                val+=(level*=.1)*D(j-'0');            return val;        }        return i;    }    SI getSI(void)    {        II j;        while(isspace(j=get()));        B neg=false;        if(j=='-')        {            neg=true;            j=get();        }#ifdef UsingIOException        if(!isdigit(j))            throw j==Eof?FileEof:TypeError;#endif        SI i=j-'0';        while(isdigit(j=get()))            i=(i<<3)+(i<<1)+(j-'0');        return neg?-i:i;    }    II getII(void)    {        II j;        while(isspace(j=get()));#ifdef UsingIOException        if(!isdigit(j))            throw j==Eof?FileEof:TypeError;#endif        II i=j-'0';        while(isdigit(j=get()))            i=(i<<3)+(i<<1)+(j-'0');        return i;    }    II getS(void)    {        II j;        while(isspace(j=get()));#ifdef UsingIOException        if(!isascii(j))            throw j==Eof?FileEof:TypeError;#endif        return j;    }    C * getCS(C *p)    {        skip();        while(!isspace(*p++=get()));        *--p='\0';        return p;    }    void skip(int (*const func)(int)=isspace)    {        while(func(get()));        --begin;    }}scan;static class Printer{    typedef unsigned int long II;    typedef char C;    static II const ScL =16384,Ral =100;    C self[ScL+Ral],*sp,*const slimit;    FILE *const buffer;public:#ifdef Fout    Printer(FILE *const iobuffer=fopen(Fout,"wb")):sp(self),slimit(self+ScL),buffer(iobuffer)#else    Printer(FILE *const iobuffer=stdout):sp(self),slimit(self+ScL),buffer(iobuffer)#endif    {    }    ~Printer(void)    {        flush();        fclose(buffer);    }    void flush(void)    {        fwrite(self,1,sp-self,buffer);        sp=self;    }    void print(C const *const s,...)    {        va_list h;        va_start(h,s);        if((sp+=vsprintf(sp,s,h))>=slimit)            flush();        va_end(h);    }    void puts(C const *const s)    {        if((sp+=strlen(strcpy(sp,s)))>=slimit)            flush();    }    void putchar(II const x)    {        *sp++=(C)x;        if(sp>=slimit)            flush();    }}sysout;vector <int> a[maxn];queue <int> q;int du[maxn],sum[maxn],dep[maxn];int n,l,ans,cnt;void Toposort(){    for(int i=1;i<=n;i++)        if(du[i]==1) q.push(i),dep[i]=1,sum[1]++;    while(!s.empty()){        int x=q.front(); q.pop();        int len=a[x].size();        cnt=max(cnt,dep[x]);        for(int i=0;i<len;i++)            if(du[a[x][i]]!=1){                du[a[x][i]]--;                if(du[a[x][i]]==1){                    dep[a[x][i]]=dep[x]+1;                    sum[dep[x]+1]++;                    q.push(a[x][i]);                }            }    }    for(int i=1;i<=cnt;i++)        ans+=min(2*l,sum[i]);}int main(){    n=scan.getSI(); l=scan.getSI();    for(int i=1;i<n;i++){        int x,y;        x=scan.getSI();        y=scan.getSI();        a[x].push_back(y);        a[y].push_back(x);        du[x]++; du[y]++;       }    Toposort();    printf("%d",ans);    return 0;   }
0 0