求助卡常

SP1825 FTOUR2 - Free tour II

feecle6418 @ 2019-07-30 16:57:12

RT,SPOJ上显示在最后一个点TLE掉了,在本校OJ上都过了。。。求卡常方法

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#include<bits/stdc++.h>
using namespace std;
struct Edge{
    int to,next,value;
}e[400005];
struct Subtree{
    int maxblack,torootval,point;
    bool operator <(const Subtree st) const {
        return maxblack<st.maxblack;
    }
}t[200005];
int h[200005],cnt,n,m,k,black[200005],size[200005];
int used[200005],sons,center,minn;
long long ans,mdb[200005],premdb[200005];
//mdb[w]:max dist with at most w black points in this subtree
//premdb[w]:max dist with at most w black points in previous subtrees
inline char get_char(){
    static char buf[1000001],*p1=buf,*p2=buf;
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++;
}
#ifdef ROBERT
#define get_char getchar
#endif
inline int read() {
    char ch;
    int x=0,ff=1;
    do {
        ch=get_char();
    } while((ch<'0'||'9'<ch)&&ch!='-');
    if(ch=='-')ff=-1,ch=get_char();
    while('0'<=ch&&ch<='9') {
        x=10*x+ch-'0';
        ch=get_char();
    }
    return x*ff;
}
inline void Add_Edge(int x,int y,int z){
    e[++cnt].to=y;
    e[cnt].value=z;
    e[cnt].next=h[x];
    h[x]=cnt;
}
inline void Add_Son(int mb,int trv,int p){
    t[++sons].maxblack=mb;
    t[sons].torootval=trv;
    t[sons].point=p;
}
void Get_Size(int now,int fa){
    size[now]=1;
    for(register int i=h[now];i;i=e[i].next){
        register int y=e[i].to;
        if(y==fa)continue;
        Get_Size(y,now);
        size[now]+=size[y];
    }
}
void Find_Center(int now,int fa,int all){
    int maxx=0;
    for(register int i=h[now];i;i=e[i].next){
        register int y=e[i].to;
        if(y==fa||used[y])continue;
        Find_Center(y,now,all);
        maxx=max(maxx,size[y]);
    }
    maxx=max(maxx,all-size[now]);
    if(maxx<minn)minn=maxx,center=now;
}
void Find_Max_Black(int now,int fa,int belong,int num){
    if(black[now])num++;
    if(num>k)return ;
    t[belong].maxblack=max(t[belong].maxblack,num);
    for(register int i=h[now];i;i=e[i].next){
        register int y=e[i].to;
        if(y==fa||used[y])continue;
        Find_Max_Black(y,now,belong,num);
    }
}
void Find_Longest_Path(int now,int fa,long long dis,int num){
    if(black[now])num++;
    if(num>k)return ;
    mdb[num]=max(mdb[num],dis);
    for(register int i=h[now];i;i=e[i].next){
        register int y=e[i].to;
        if(y==fa||used[y])continue;
        Find_Longest_Path(y,now,dis+e[i].value,num);
    }
}
void Dianfenzhi(int now){
    register int i,j,y,bf;
    center=0,minn=0x3f3f3f3f,sons=0;
    Find_Center(now,0,size[now]);
    used[center]=1;
    for(i=h[center];i;i=e[i].next){
        y=e[i].to;
        if(used[y])continue;
        Add_Son(0,e[i].value,y);
        Find_Max_Black(y,center,sons,0);
    }
    sort(t+1,t+sons+1);
    for(i=0;i<=t[sons].maxblack;i++)premdb[i]=0;
    for(i=1;i<=sons;i++){
        y=t[i].point;
        for(j=0;j<=t[i].maxblack;j++)mdb[j]=-0x3f3f3f3f3f3f3f3fll;
        Find_Longest_Path(y,center,t[i].torootval,0);
        for(j=1;j<=t[i].maxblack;j++)mdb[j]=max(mdb[j],mdb[j-1]);
        for(j=0;j<=t[i].maxblack;j++){
            bf=min(t[i-1].maxblack,k-j-black[center]);//bf:before
            if(bf<0)continue;
            ans=max(ans,premdb[bf]+mdb[j]);
        }
        for(j=0;j<=t[i].maxblack;j++)premdb[j]=max(premdb[j],mdb[j]);
        for(j=1;j<=t[i].maxblack;j++)premdb[j]=max(premdb[j],premdb[j-1]);
    }
    for(i=h[center];i;i=e[i].next){
        y=e[i].to;
        if(!used[y])Dianfenzhi(y);
    }
}
signed main(){
    n=read(),k=read(),m=read();
    for(int i=1,x;i<=m;i++){
        x=read();
        black[x]=1;
    }
    for(int i=1,x,y,z;i<n;i++){
        x=read(),y=read(),z=read();
        Add_Edge(x,y,z);
        Add_Edge(y,x,z);
    }
    Get_Size(1,0);
    Dianfenzhi(1);
    printf("%lld\n",ans);
    return 0;
}

by FZzzz @ 2019-07-30 16:59:29

吸氧


|