1. 程式人生 > >9.24 test T2 factory工廠 題解

9.24 test T2 factory工廠 題解

【問題描述】     秋之國有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