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