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;
}