noip2018 赛道修建

先放一下代码。题解日后再补。

怎么说呢,以前老是反感猜结论,其实多猜猜就不会这么想了。

//80分部分分 乱搞做法
#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> pii;
#define forg(i,x) for(int i=first[x];i;i=nxt[i])
#define uu unsigned
#define fi first
#define se second
#define od(x) ((x)&1)
#define ev(x) (od(x)^1)
#define mi2(x) (1<<(x))
#define scanf a1234=scanf
#define fre(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout)
int a1234;
char buf[1<<18],*bufs=buf,*buft=buf;
inline int gc(){
    return bufs==buft&&(buft=(bufs=buf)+fread(buf,1,1<<18,stdin)),bufs==buft?-1:*bufs++;
}
inline void xxx(){for(;;);}

const int mxn=5e4+3;
int n,m,to[mxn<<1],nxt[mxn<<1],first[mxn],tot=1,deg[mxn],W[mxn<<1],len[mxn],rt;
inline int rd(int l,int r){return rand()%(r-l+1)+l;}
inline void gadd(int x,int y,int l){to[++tot]=y,nxt[tot]=first[x],first[x]=tot,W[tot]=l,++deg[x];}
struct duru{
    int x,y,l;
}du[mxn];
inline void dfs1(int x,int f){
    forg(i,x)if(to[i]!=f)dfs1(to[i],x),len[x]=max(len[x],W[i]+len[to[i]]);
}

namespace task1{
    int len[mxn],ans=0;
    inline void dfs(int x,int f){
        forg(i,x)if(to[i]!=f)dfs(to[i],x),ans=max(ans,len[x]+len[to[i]]+W[i]),len[x]=max(len[x],W[i]+len[to[i]]);
    }
    int main1(){
        dfs(rt,0);printf("%d\n",ans);
        return 0;
    }
}
int rh[mxn],nn=0;
inline void getrt(){
    for(int i=1;i<=n;++i)if(deg[i]<=2)rh[++nn]=i;
    rt=rh[rd(1,nn)];
}
namespace task2{
    inline bool is(){for(int i=1;i<n;++i)if(du[i].y!=du[i].x+1)return 0;return 1;}
    int w[mxn];
    inline bool can(int x){
        int cnt=0,sum=0;
        for(int i=1;i<n;++i){
            sum+=w[i];
            if(sum>=x)sum=0,++cnt;
        }
        return cnt>=m;
    }
    int main1(){
        for(int i=1;i<n;++i)w[du[i].x]=du[i].l;
        int l=1,r=5e8+11,mid;
        while(l!=r){
            mid=(l+r+1)>>1;
            if(can(mid))l=mid;else r=mid-1;
        }
        printf("%d\n",l);
        return 0;
    }
}
namespace task3{
    inline bool is(){for(int i=1;i<n;++i)if(du[i].x!=1)return 0;return 1;}
    int w[mxn];
    inline bool can(int x){
        int nn=n,cnt=0;
        for(--nn;nn&&w[nn]>=x;--nn)++cnt;
        if(nn==0)return 1;
        int l=1,r=nn;
        while(l<r){
            if(w[l]+w[r]>=x)++cnt,++l,--r;else ++l;
        }
        return cnt>=m;
    }
    int main1(){
        for(int i=1;i<n;++i)w[i]=du[i].l;
        sort(w+1,w+n);
        int l=1,r=5e8+11,mid;
        while(l!=r){
            mid=(l+r+1)>>1;
            if(can(mid))l=mid;else r=mid-1;
        }
        printf("%d\n",l);
        return 0;
    }
}
namespace task4{
    inline bool is(){for(int i=1;i<=n;++i)if(deg[i]>3)return 0;return n<=1000;}
    const int mxn=1003;
    int dp[mxn][2],ls[mxn],rs[mxn],fa[mxn],w[mxn][2],ww[mxn];
    int wan;
    inline void dfs1(int x,int f,int e){
        fa[x]=f,ww[x]=W[e];
        forg(i,x)if(to[i]!=f){
            dfs1(to[i],x,i);
            if(!ls[x])ls[x]=to[i],w[x][0]=W[i];else rs[x]=to[i],w[x][1]=W[i];
        }
    }
    inline void soul(int &f,int x,int sum,int up){
        if(len[x]+sum<wan)return;
        if(sum>=wan)return f=max(f,1+up+dp[x][0]),void();
        if(ls[x])soul(f,ls[x],sum+w[x][0],up+dp[rs[x]][1]);
        if(rs[x])soul(f,rs[x],sum+w[x][1],up+dp[ls[x]][1]);
    }
    inline void sou1(int &f,int x1,int x2,int sum,int up,bool tg){
        if(sum>=wan)return f=max(f,1+up+dp[x2][0]+dp[x1][0]),void();
        if(tg){
            if(sum+len[x2]<wan)return;
            if(ls[x2])sou1(f,x1,ls[x2],sum+w[x2][0],up+dp[rs[x2]][1],1);
            if(rs[x2])sou1(f,x1,rs[x2],sum+w[x2][1],up+dp[ls[x2]][1],1);
        }else{
            if(sum+len[x1]+len[x2]<wan)return;
            sou1(f,x1,x2,sum,up,1);
            if(ls[x1])sou1(f,ls[x1],x2,sum+w[x1][0],up+dp[rs[x1]][1],0);
            if(rs[x1])sou1(f,rs[x1],x2,sum+w[x1][1],up+dp[ls[x1]][1],0);
        }
    }

    inline void dfs(int x){
        if(ls[x])dfs(ls[x]);if(rs[x])dfs(rs[x]);
        dp[x][0]=max(dp[ls[x]][0]+dp[rs[x]][1],dp[rs[x]][0]+dp[ls[x]][1]);
        soul(dp[x][0],x,0,0);
        if(ls[x]&&rs[x])sou1(dp[x][0],ls[x],rs[x],w[x][0]+w[x][1],0,0);
        if(x==rt||ww[x]>=wan)return dp[x][1]=dp[x][0]+1,void();
        dp[x][1]=dp[x][0];
        soul(dp[x][1],x,ww[x],0);
    }
    inline bool can(){
        memset(dp,0,sizeof(dp));
        dfs(rt);
        return dp[rt][0]>=m;
    }
    int main1(){
//    puts("OKKKKKKKKKKKKKKKKK");
        dfs1(rt,0,0);
        int l=1,r=n*10000;
        while(l<r){
            wan=(l+r+1)>>1;
            if(can())l=wan;else r=wan-1;
        }
        printf("%d\n",l);
        return 0;
    }
}
int main(){
    srand((uu)time(0));
    scanf("%d%d",&n,&m);for(int i=1,u,v,l;i<n;++i)scanf("%d%d%d",&u,&v,&l),du[i]=(duru){u,v,l},gadd(u,v,l),gadd(v,u,l);
    getrt();
    dfs1(rt,0);
    if(task4::is())return task4::main1();
//    puts("ohwwwwwwwwwww");
    if(m==1)return task1::main1();
    if(task2::is())return task2::main1();
    if(task3::is())return task3::main1();
    return 0;
}

#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> pii;
#define forg(i,x) for(int i=first[x];i;i=nxt[i])
#define uu unsigned
#define fi first
#define se second
#define od(x) ((x)&1)
#define ev(x) (od(x)^1)
#define mi2(x) (1<<(x))
#define scanf a1234=scanf
#define fre(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout)
#define fp fprintf
int a1234;
char buf[1<<18],*bufs=buf,*buft=buf;
inline int gc(){
    return bufs==buft&&(buft=(bufs=buf)+fread(buf,1,1<<18,stdin)),bufs==buft?-1:*bufs++;
}
inline void xxx(){for(;;);}
inline int rd(int l,int r){return rand()%(r-l+1)+l;}
FILE*fo;
int tmp[1003];
inline void dfs(int l,int r){
    if(l==r)return;
    int lc=rd(1,r-l);
    if(lc==r-l)return fp(fo,"%d %d %d\n",tmp[l],tmp[l+1],rd(1,10000)),dfs(l+1,r);
    dfs(l+1,l+lc),dfs(l+lc+1,r);
    fp(fo,"%d %d %d\n",tmp[l],tmp[l+1],rd(1,10000)),fp(fo,"%d %d %d\n",tmp[l],tmp[l+lc+1],rd(1,10000));
}
inline void maked(){
    fo=fopen("te.in","w");
    int n=1000,m=rd(1,n-1);
    for(int i=1;i<=n;++i)tmp[i]=i;random_shuffle(tmp+1,tmp+n+1);
    fp(fo,"%d %d\n",n,m);
    dfs(1,n);
    fclose(fo);
}
inline uu work(){
    maked();
    system("./a<te.in>1.ans"),system("./b<te.in>2.ans");
    return system("diff 1.ans 2.ans -b -B -q");
}
int main(){
    srand((uu)time(0));
    //return maked(),3;
    system("g++ a.cpp -O2 -Wall -o a"),system("g++ b.cpp -O2 -Wall -o b");
    int cases=0;
    while(1){printf("%d\n",++cases);if(work())return 222;if(cases==1000)return 0;}
    return 0;
}

posted @ 2020-10-14 21:33  yugyppah656  阅读(135)  评论(0编辑  收藏  举报