蓝桥杯撞题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;
}
标签:ch,pw,fw,稳定性,蓝桥,100000,2023,buf,define
From: https://www.cnblogs.com/SHOJYS/p/17398900.html