疫情控制 40

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=50001; 


int n,m;
int head[maxn];
int num_edge=0;
int f[maxn][20],d[maxn][20];
int deep[maxn];


 


struct edge{
int from,to,nxt,len;
}edge[2*maxn];


void add(int u,int v,int w)
{
edge[++num_edge].from=u;
edge[num_edge].to=v;
edge[num_edge].len=w;
edge[num_edge].nxt=head[u];
head[u]=num_edge;
}


int p[maxn];
int zuzong[maxn];
int num_son=0;
bool flu[maxn];
int max_time=0;
int father[maxn];
int num_bj=0;
int bj[maxn];
int many_bj[maxn];
int many[maxn];




void build(int u)
{
int s=0;
for(int i=head[u];i;i=edge[i].nxt)
{
int v=edge[i].to;
if(v==father[u])
continue;
++s;
father[v]=u;
deep[v]=deep[u]+1;
f[v][0]=u;
d[v][0]=edge[i].len;

if(father[v]==1)
zuzong[v]=v;
else
zuzong[v]=zuzong[u];

build(v);
}
if(s==0)
bj[++num_bj]=u;
}


struct arrive1{
int left,point;
}arrive[maxn];




bool cmp(arrive1 a,arrive1 b)
{
return a.left<b.left;
}


void dfs(int u)
{
for(int i=head[u];i;i=edge[i].nxt)
{
int v=edge[i].to;
if(father[v]==u)
continue;
if(u!=1)
{
if(!flu[u])
flu[v]=false;
}
dfs(v);

}

}


bool cmp2(int a,int b)
{
return d[a][0]<=d[b][0];
}
bool check(int time)
{
int num_arrive=0;
memset(flu,1,sizeof(flu));
// memset(many,0,sizeof(many));
for(int i=1;i<=m;i++)
{
int t=time;
int point = p[i];
for(int j=17;j>=0;j--)
{
if(f[point][j]&&d[point][j]<=t)
{
t-=d[point][j];
point=f[point][j];
}

}
if(point==1)
{
arrive[++num_arrive].left=t;
arrive[num_arrive].point=zuzong[p[i]];
}
else
{
flu[point]=false;
}
}

sort(arrive+1,arrive+num_arrive+1,cmp);
dfs(1);
for(int i=1;i<=num_bj;i++)
{
if(!flu[bj[i]])
{
--many[zuzong[bj[i]]];
}
}
bool used[maxn];
memset(used,0,sizeof(used));
int num_army=num_arrive;

for(int i=1;i<=num_arrive;i++)
{
int point=arrive[1].point;
int left=arrive[i].left;
if(many[point]&&flu[point]&&left<d[point][0])
{
flu[point]=false;
used[i]=1;
num_army--;
}

dfs(1);
}

int cnt=0;
int fb[maxn];
for(int i=1;i<=num_bj;i++)
{
if(flu[bj[i]]&&flu[zuzong[bj[i]]])
{
fb[++cnt]=zuzong[bj[i]];
flu[zuzong[bj[i]]]=false;
}
}
if(cnt==0)
return 1;

if(cnt>num_army)
return 0;

sort(fb+1,fb+cnt+1,cmp2);

int j=1;
for(int i=1;i<=num_arrive;i++)
{
if(used[i])
continue;

if(d[fb[j]][0]<=arrive[i].left)
{
cnt--;
j++;
}
if(cnt==0)
return 1;

}

return 0;






}






int main()
{
cin>>n;



for(int i=1;i<n;i++)
{
int u,v,w;
cin>>u>>v>>w;
add(u,v,w);
add(v,u,w);
max_time+=v;
}


cin>>m;
for(int i=1;i<=m;i++)
cin>>p[i];



for(int i=head[1];i;i=edge[i].nxt)
{
// cout<<edge[i].to<<endl;
num_son++;
}


if(m<num_son)
{
cout<<-1;
return 0;
}


deep[1]=0;
build(1);


for(int i=1;i<=17;i++)
{
for(int j=1;j<=n;j++)
{
f[j][i]=f[f[j][i-1]][i-1];
d[j][i]=d[j][i-1]+d[f[j][i-1]][i-1];
}
}


for(int i=1;i<=num_bj;i++)
{
++many[zuzong[bj[i]]];
}


int l=0,r=max_time;
int res=-1;

/*
while(l<r)
{

int mid=(l+r)/2;
// cout<<"l: "<<l<<" r: "<<r<<" mid: "<<mid<<endl;
if(check(mid))
{
res=mid;
r=mid;
}
else
{
l=mid+1;
}
// cout<<res<<endl;
}

cout<<res;*/
cout<<check(9);



return 0;
 } 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值