bzoj3732 Network(NOIP2013 货车运输)
Description
给你N个点的无向图 (1 <= N <= 15,000),记为:1…N。
图中有M条边 (1 <= M <= 30,000) ,第j条边的长度为: d_j ( 1 < = d_j < = 1,000,000,000).
现在有 K个询问 (1 < = K < = 20,000)。
每个询问的格式是:A B,表示询问从A点走到B点的所有路径中,最长的边最小值是多少?
Input
第一行: N, M, K。
第2..M+1行: 三个正整数:X, Y, and D (1 <= X <=N; 1 <= Y <= N). 表示X与Y之间有一条长度为D的边。
第M+2..M+K+1行: 每行两个整数A B,表示询问从A点走到B点的所有路径中,最长的边最小值是多少?
Output
对每个询问,输出最长的边最小值是多少。
Sample Input
6 6 8
1 2 5
2 3 4
3 4 3
1 4 8
2 5 7
4 6 2
1 2
1 3
1 4
2 3
2 4
5 1
6 2
6 1
1 2 5
2 3 4
3 4 3
1 4 8
2 5 7
4 6 2
1 2
1 3
1 4
2 3
2 4
5 1
6 2
6 1
Sample Output
5
5
5
4
4
7
4
5
5
5
4
4
7
4
5
HINT
1 <= N <= 15,000
1 <= M <= 30,000
1 <= d_j <= 1,000,000,000
1 <= K <= 15,000
最小生成树+倍增求lca
//Serene #include<algorithm> #include<iostream> #include<cstring> #include<cstdlib> #include<cstdio> #include<cmath> using namespace std; const int maxn=15000+10,maxm=30000+10; int n,m,k,faf[maxn],tot; struct Node{ int x,y,d; bool operator <(const Node& b) const{return d<b.d;} }node[maxm]; int aa;char cc; int read() { aa=0;cc=getchar(); while(cc<'0'||cc>'9') cc=getchar(); while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar(); return aa; } int find(int x) { return faf[x]==x? x:faf[x]=find(faf[x]); } int fir[maxn],to[2*maxn],nxt[2*maxn],val[2*maxn],e=0; void add(int x,int y,int z) { to[++e]=y;nxt[e]=fir[x];fir[x]=e;val[e]=z; to[++e]=x;nxt[e]=fir[y];fir[y]=e;val[e]=z; } int dep[maxn],fa[maxn][20],ans[maxn][20]; void dfs(int pos,int h) { dep[pos]=h; for(int y=fir[pos];y;y=nxt[y]) { if(to[y]==fa[pos][0]) continue; fa[to[y]][0]=pos; ans[to[y]][0]=val[y]; dfs(to[y],h+1); } } int mi[20],cha,rs; int LCA(int x,int y) { rs=1; if(dep[x]!=dep[y]) { if(dep[x]<dep[y]) swap(x,y); cha=dep[x]-dep[y]; for(int i=tot;i>=0;--i) if(cha>=mi[i]) { rs=max(rs,ans[x][i]); cha-=mi[i]; x=fa[x][i]; if(!cha) break; } } int xx,yy,d; while(x!=y) { xx=x;yy=y;d=-1; while(xx!=yy) { if(d>=0) rs=max(rs,ans[x][d]),rs=max(rs,ans[y][d]); x=xx;y=yy; xx=fa[x][++d]; yy=fa[y][d]; } if(d==0) rs=max(rs,ans[x][d]),rs=max(rs,ans[y][d]),x=xx,y=yy; } return rs; } int main() { n=read();m=read();k=read(); int a,b; for(int i=1;i<=m;++i) { node[i].x=read();node[i].y=read();node[i].d=read(); } sort(node+1,node+m+1); for(int i=1;i<=n;++i) faf[i]=i; for(int i=1;i<=m;++i) { a=find(node[i].x);b=find(node[i].y); if(a!=b) { faf[a]=b;tot++; add(node[i].x,node[i].y,node[i].d); } if(tot==n-1) break; } dfs(1,1); tot=-1; for(int i=1;i<n*2;i<<=1) mi[++tot]=i; for(int i=1;i<=tot;++i) for(int j=1;j<=n;++j) { fa[j][i]=fa[fa[j][i-1]][i-1]; ans[j][i]=max(ans[j][i-1],ans[fa[j][i-1]][i-1]); } for(int i=1;i<=k;++i) { a=read();b=read(); printf("%d\n",LCA(a,b)); } return 0; }
弱者就是会被欺负呀