【问题描述】
秋之国有n个城市(编号为1到n)和n − 1条双向道路,每条道路的长度均为1,任意两个城市之间都可以互相到达。
小D打算选择一个城市建工厂,他生产的货品需要m种原料,其中第?种可以在城市a?买到。小 D 希望工厂所在的城市到每个a?的距离都不超过d。
秋之国的道路经常发生变动,小D 会告诉你道路的变动情况,并给出若干次询问,每次你需要回答当前有多少个城市可以作为工厂的所在地。
【输入格式】
第一行四个正整数n,m,q,d,其中q表示事件数。
第二行m个正整数,表示a?。
接下来n − 1行,每行两个正整数,表示一条道路的两个端点。
接下来q行,每行先是一个正整数opt。 若opt = 1,接下来还有三个正整数p,x,y,表示第p条给出的道路被移除(可能是新增的道路,保证这条道路还未被移除) ,并新增一条连接x和y的道路,保证任意时刻任意两个城市之间都能相互到达。若opt = 2,表示一次询问。
【输出格式】
对于每个询问输出一行一个整数,表示答案。
【样例输入】
4 2 5 1
1 2
1 2
2 3
3 4
2
1 1 1 4
2
1 4 1 3
2
【样例输出】
2
0
1
【数据范围】
对于30%的数据,n,m,q ≤ 100。对于70%的数据,n,m,q ≤ 5000。对于 100%的数据,n,m,q ≤ 30000,d≤n,保证询问数不超过100。
【题解】
先从任意点开始一重dfs找离他最远的关键点,然后再一次dfs从此关键点开始找离他最远的关键点。
此时这就是所有关键点里面相距最远的两个关键点,在这同时我们还要存储每个点离这两个点的距离。
然后我们直接进行距离的判断,这样就可以统计出答案。
【AC Code】
#include<bits/stdc++.h>
using namespace std;
namespace init{
char buf[1<<15],*fs,*ft;
inline char getc(){return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;}
inline int read(){
int x=0,f=1; char ch=getc();
while(!isdigit(ch)) {if(ch=='-') f=-1; ch=getc();}
while(isdigit(ch)) {x=(x<<3)+(x<<1)+ch-'0'; ch=getc();}
return x*f;
}
}using namespace init;
int n,m,q,d;
int a[120010];
bool vis[120010],KEY[120010];
int linkk[120010],len;
struct edge{
int to,next,w;
}e[120010];
void insert(int x,int y,int w)
{
e[++len].to=y,e[len].next=linkk[x],linkk[x]=len,e[len].w=w;
}
int max_dis,max_id,max_dis_next,max_id_next;
int dis1[30010],dis2[30010],cnt;
void dfs(int x,int dis_)
{
vis[x]=1;
for(int i=linkk[x];i;i=e[i].next)
{
int v=e[i].to;
if(!e[i].w||vis[v]) continue;
dis2[v]=dis2[x]+e[i].w;
if(dis2[v]>d&&dis1[v]<=d) --cnt;
dfs(v,dis_+e[i].w);
}
}
void dfs1(int x,int dis_)
{
if(max_dis<dis_&&KEY[x]) max_dis=dis_,max_id=x;
vis[x]=1;
// dis1[x]=0;
for(int i=linkk[x];i;i=e[i].next)
{
int v=e[i].to;
if(!e[i].w||vis[v]) continue;
dfs1(v,dis_+e[i].w);
}
}
void dfs2(int x,int dis_)
{
if(max_dis_next<dis_&&KEY[x]) max_dis_next=dis_,max_id_next=x;
vis[x]=1;
// dis2[x]=0;
for(int i=linkk[x];i;i=e[i].next)
{
int v=e[i].to;
if(!e[i].w||vis[v]) continue;
dis1[v]=dis1[x]+e[i].w;
if(dis1[v]>d) --cnt;
dfs2(v,dis_+e[i].w);}
}
void solve()
{
cnt=n;
max_dis=max_dis_next=0;
// memset(dis1,0,sizeof(dis1));
// memset(dis2,0,sizeof(dis2));
for(int i=1;i<=3;++i)
{
memset(vis,0,sizeof(vis));
if(i==1) dfs1(1,0);
if(i==2) dis1[max_id]=0,dfs2(max_id,0);
if(i==3) dis2[max_id_next]=0,dfs(max_id_next,0);
}
// cout<<max_id<<' '<<max_dis
//for(int i=1;i<=n;++i) if(dis[i]<=d) ++cnt;
//for(int i=1;i<=n;++i) printf("%d ",dis[i]);
//puts("");
// cout<<max_dis<<' '<<max_id<<' '<<max_dis_next<<' '<<max_id_next<<endl;
// for(int i=1;i<=n;++i) cout<<dis1[i]<<' '<<dis2[i]<<endl;
printf("%d\n",cnt);
}
int main()
{
freopen("factory.in","r",stdin);
freopen("factory.out","w",stdout);
n=read(),m=read(),q=read(),d=read();
for(int i=1;i<=m;++i) KEY[a[i]=read()]=1;
for(int x,y,i=1;i<n;++i)
{
x=read(),y=read();
insert(x,y,1);
insert(y,x,1);
}
for(int opt,x,y,p,i=1;i<=q;++i)
{
opt=read();
if(opt==1)
{
p=read(),x=read(),y=read();
e[(p<<1)-1].w=e[p<<1].w=0;
insert(x,y,1);
insert(y,x,1);
}
else solve();
}
//system("pause");
return 0;
}
ORZ