【做题记录】蓝桥杯 2023 省 A 网络稳定性

蓝桥杯撞题NOIP原题,做法也一模一样(撞题:NOIP2013提高组 货车运输)
由题意可得这是让我们先求一个最大生成树(把求最小生成树反过来求即可),再求最小边权。
求最大生成树我们可以用并查集+排序做出。
求最小边权我们可以LCA,也可以树链剖分+线段树维护。后者码量太大(本人太懒),没打算写。
代码:

#include<cstdlib>
#include<cstdio>
#include<cctype>
typedef long long LL;
typedef unsigned long long ULL;
namespace FastIo{
    typedef __uint128_t L;
    static char buf[100000],*p1=buf,*p2=buf,fw[100000],*pw=fw;
    #define gc p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++
    inline void pc(const char &ch){
    	if(pw-fw==100000)fwrite(fw,1,100000,stdout),pw=fw;
    	*pw++=ch;
	}
    #define fsh fwrite(fw,1,pw-fw,stdout),pw=fw
	struct FastMod{
        FastMod(ULL b):b(b),m(ULL((L(1)<<64)/b)){}
        ULL reduce(ULL a){
            ULL q=(ULL)((L(m)*a)>>64);
            ULL r=a-q*b;
            return r>=b?r-b:r;
        }
        ULL b,m;
    }HPOP(10);
    struct QIO{
    	char ch;
    	int st[40];
    	template<class T>inline void read(T &x){
    		x=0,ch=gc;
    		while(!isdigit(ch))ch=gc;
    		while(isdigit(ch)){x=(x<<3)+(x<<1)+(ch^48);ch=gc;}
		}
		template<class T>inline void write(T a){
			if(a<0)a=-a,pc('-');
			do{st[++st[0]]=HPOP.reduce(a);a/=10;}while(a);
			while(st[0])pc(st[st[0]--]^48);
			pc('\n');
		}
	}qrw;
}
using namespace FastIo;
#define P(A) A=-~A
#define fione(begin,end) for(register int i=begin;i<=end;P(i))
#define fdone(begin,end) for(register int i=begin;i>=end;--i)
#include<algorithm>
#define INF 10e8+5
#define NUMLCA 20
#define NUMBER1 100000
#define NUMBER2 300000
struct edge{
	int u,v,dis;
	bool operator<(const edge &a)const{return dis>a.dis;}
}ed[NUMBER2+2];
struct NODE{int next,to,w;}e[(NUMBER2<<1)+5];
int head[NUMBER1+5],f[NUMBER1+5],fa[NUMBER1+5][NUMLCA+2],worth[NUMBER1+5][NUMLCA+2],tot(0),depth[NUMBER1+5];
bool visit[NUMBER1+5];
inline void add(int u,int v,int w){e[++tot].next=head[u];e[tot].to=v,e[tot].w=w,head[u]=tot;}
int find(int x){return x==f[x]?f[x]:f[x]=find(f[x]);}
void lca_dfs(int u){
	visit[u]=true;
	for(register int i=head[u];i;i=e[i].next)
		if(!visit[e[i].to]){
			depth[e[i].to]=depth[u]+1,fa[e[i].to][0]=u,worth[e[i].to][0]=e[i].w;
			lca_dfs(e[i].to);
		}
}
inline void LCA(int x,int y){
	if(find(x)!=find(y))return qrw.write(-1),void();
	if(depth[x]>depth[y])std::swap(x,y);
	int c=depth[y]-depth[x],ans(INF);
	fdone(NUMLCA,0)
		if(c&(1<<i)){
			ans=std::min(ans,worth[y][i]);
			y=fa[y][i];
		}
	if(x==y)return qrw.write(ans),void();
	fdone(NUMLCA,0)
		if(fa[x][i]!=fa[y][i]){
			ans=std::min(ans,std::min(worth[x][i],worth[y][i]));
			x=fa[x][i],y=fa[y][i];
		}
	qrw.write(std::min(ans,std::min(worth[x][0],worth[y][0])));
}
signed main(){
	int n,m,q,u,v,w;
	qrw.read(n);
	qrw.read(m);
	qrw.read(q);
	fione(1,m){
		qrw.read(u);
		qrw.read(v);
		qrw.read(w);
		ed[i].u=u,ed[i].v=v,ed[i].dis=w;
	}
	fione(1,n)f[i]=i;
	std::sort(ed+1,ed+1+m);
	fione(1,m){
		u=find(ed[i].u),v=find(ed[i].v);
		if(u==v)continue;
		f[u]=v;
		add(ed[i].u,ed[i].v,ed[i].dis);
		add(ed[i].v,ed[i].u,ed[i].dis);
	}
	fione(1,n)
		if(!visit[i]){
			depth[i]=1;
			lca_dfs(i);
			fa[i][0]=i,worth[i][0]=INF;
		}
	for(register int j(1);j<=NUMLCA;P(j))
		fione(1,n){
			fa[i][j]=fa[fa[i][j-1]][j-1];
			worth[i][j]=std::min(worth[i][j-1],worth[fa[i][j-1]][j-1]);
		}
	while(q--){
		qrw.read(u);
		qrw.read(v);
		LCA(u,v);
	}
	fsh;
    exit(0);
    return 0;
}
posted @ 2023-05-14 10:52  SHOJYS  阅读(81)  评论(0编辑  收藏  举报