水题,前几年的NOIP题目。
先求出最小生成树,然后在树上求LCA就可以了,记得维护一下。
结果调试输出忘删了。
#include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<iostream> #include<algorithm> #define maxn 15010 #define inf 1000000010 using namespace std; struct yts { int x,y,len; }e[30010]; int next[2*maxn],to[2*maxn],len[2*maxn],g[2*maxn],fa[maxn][20],ans[maxn][20],head[maxn],dis[maxn]; int n,m,T,num,cnt; int f[maxn],dep[maxn]; bool cmp(yts x,yts y) { return x.len<y.len; } int find(int x) { if (f[x]==x) return x; else return f[x]=find(f[x]); } void addedge(int x,int y,int z) { num++;to[num]=y;len[num]=z;next[num]=head[x];head[x]=num; num++;to[num]=x;len[num]=z;next[num]=head[y];head[y]=num; } void dfs(int x) { for (int p=head[x];p;p=next[p]) if (to[p]!=g[x]) { g[to[p]]=x;dis[to[p]]=len[p];dep[to[p]]=dep[x]+1; dfs(to[p]); } } int go_up(int x,int d) { for (int i=19;i>=0;i--) if (d&(1<<i)) cnt=max(cnt,ans[x][i]),x=fa[x][i]; return x; } int LCA(int x,int y) { if (dep[x]>dep[y]) x=go_up(x,dep[x]-dep[y]); else y=go_up(y,dep[y]-dep[x]); if (x==y) return cnt; for (int i=19;i>=0;i--) if (fa[x][i]!=fa[y][i]) { cnt=max(cnt,max(ans[x][i],ans[y][i])); x=fa[x][i];y=fa[y][i]; } return max(cnt,max(dis[x],dis[y])); } int main() { scanf("%d%d%d",&n,&m,&T); for (int i=1;i<=m;i++) scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].len); sort(e+1,e+m+1,cmp); for (int i=1;i<=n;i++) f[i]=i; for (int i=1;i<=m;i++) { int f1=find(e[i].x),f2=find(e[i].y); if (f1!=f2) { f[f1]=f2; addedge(e[i].x,e[i].y,e[i].len); } } g[1]=0;dis[1]=0; dfs(1); for (int i=1;i<=n;i++) fa[i][0]=g[i]; for (int j=1;j<=19;j++) for (int i=1;i<=n;i++) if (fa[i][j-1]) fa[i][j]=fa[fa[i][j-1]][j-1]; else fa[i][j]=0; for (int i=1;i<=n;i++) ans[i][0]=dis[i]; for (int j=1;j<=19;j++) for (int i=1;i<=n;i++) if (fa[i][j-1]) ans[i][j]=max(ans[i][j-1],ans[fa[i][j-1]][j-1]); while (T--) { int x,y; scanf("%d%d",&x,&y); cnt=0; printf("%d\n",LCA(x,y)); } return 0; }