论证代码时间复杂度
查看原帖
论证代码时间复杂度
742533
hzxphy楼主2024/8/26 21:07
#include<bits/stdc++.h>
#define AUTO(i,u) for(int (i)=G.head[(u)];(i)!=-1;(i)=G.nxt[i])
using namespace std;
int N,M,S;
int deep[200010];
int st[200010][30];
struct Grape{
    int head[200010];
    int nxt[400010];
    int to[400010];
    void Emplace_back(int u,int v){
        to[++c]=v;
        nxt[c]=head[u];
        head[u]=c;
        return;
    }
    void clear(void){
        *this=Grape();
        return;
    }
    Grape(){
        c=0;
        memset(head,-1,sizeof head);
        memset(nxt,-1,sizeof nxt);
        memset(to,0,sizeof to);
    }
    int c;
}G;
int fa[200001];
bool cmp(int x,int y){
    return deep[x]<deep[y];
}
void InitDeep(int u,int par){
	deep[u]=deep[par]+1;
	st[u][0]=par;
	fa[u]=par;
	for(int i=1;(1<<i)<=deep[u];i++){
		st[u][i]=st[st[u][i-1]][i-1];
	}
	AUTO(i,u){
		int To=G.to[i];
		if(To!=par)InitDeep(To,u);
	}
	return;
}
int LCA(int a,int b){
	if(deep[a]>deep[b])swap(a,b);
	for(int i=20;i>=0;i--){
		if(deep[a]<=deep[b]-(1<<i)){
			b=st[b][i];
		}
	}
	if(a==b)return a;
	for(int i=20;i>=0;i--){
		if(st[a][i]==st[b][i]){
			continue;
		}
		a=st[a][i];
		b=st[b][i];
	}
	return st[a][0];
}
int ans=0;
int q[200001];
bool vis[200001];
void DFS(int u,int ppar){
    vis[u]=true;
    if(u==ppar){
        return;
    }
    DFS(fa[u],ppar);
    return;
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    srand(time(0));
	cin>>N>>M;S=rand()%N;
	for(int i=1;i<N;i++){
		int u,v;
		cin>>u>>v;
		G.Emplace_back(u,v);
		G.Emplace_back(v,u);
	}
	InitDeep(S,0);
	for(int i=1;i<=M;i++){
        cin>>q[i];vis[q[i]]=1;
	}
	sort(q+1,q+1+M,cmp);
	for(int i=1;i<M;i++){
        int lca=LCA(q[i],q[i+1]);
//        cout<<lca<<' '<<q[i]<<' '<<q[i+1]<<'\n';
        DFS(q[i],lca);
        DFS(q[i+1],lca);
	}
	for(int i=1;i<=N;i++){
        if(vis[i])ans++;
	}
	cout<<ans;
	return 0;
}

大致思路是用 LCA 解决,排序弄掉尽可能多的重复节点遍历,而有时树会退化为链,将根节点随机设定。

2024/8/26 21:07
加载中...