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
吸氧