BZOJ3732: Network
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
题解Here!
在$BZOJ$闲逛的时候发现了这题。
这$TM$不是$NOIP2013\text{货车运输}$嘛。。。
顺手码了。。。
然而这种沙茶题我竟然没有$1A$,真是太失败了。。。
然后发现,我$TM$竟然手抽了,把$will$打成了$f$。。。
手残。。。
所以一发$Kruskal+LCA+\text{树链剖分}$就好了。
附代码:
#include<iostream> #include<algorithm> #include<cstdio> #define LSON rt<<1 #define RSON rt<<1|1 #define DATA(x) b[x].data #define LSIDE(x) b[x].l #define RSIDE(x) b[x].r #define MAXN 20010 using namespace std; int n,m,q,c=1,d=1; int father[MAXN],head[MAXN],deep[MAXN],son[MAXN],size[MAXN],fa[MAXN],id[MAXN],top[MAXN]; struct Tree{ int next,to; }a[MAXN<<1]; struct Segment_Tree{ int data,l,r; }b[MAXN<<2]; struct Edge{ int u,v,w; bool used; }g[MAXN<<1]; inline int read(){ int date=0,w=1;char c=0; while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();} while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();} return date*w; } inline bool cmp(const Edge &p,const Edge &q){return p.w<q.w;} int find(int x){return father[x]==x?x:father[x]=find(father[x]);} inline void uniun(int x,int y){x=find(x);y=find(y);if(x!=y)father[y]=x;} inline void add(int x,int y){ a[c].to=y;a[c].next=head[x];head[x]=c++; a[c].to=x;a[c].next=head[y];head[y]=c++; } void dfs1(int rt){ son[rt]=0;size[rt]=1; for(int i=head[rt];i;i=a[i].next){ int will=a[i].to; if(!deep[will]){ deep[will]=deep[rt]+1; fa[will]=rt; dfs1(will); size[rt]+=size[will]; if(size[son[rt]]<size[will])son[rt]=will; } } } void dfs2(int rt,int f){ id[rt]=d++;top[rt]=f; if(son[rt])dfs2(son[rt],f); for(int i=head[rt];i;i=a[i].next){ int will=a[i].to; if(will!=fa[rt]&&will!=son[rt])dfs2(will,will); } } inline void pushup(int rt){ DATA(rt)=max(DATA(LSON),DATA(RSON)); } void buildtree(int l,int r,int rt){ LSIDE(rt)=l;RSIDE(rt)=r; if(l==r){ DATA(rt)=0; return; } int mid=l+r>>1; buildtree(l,mid,LSON); buildtree(mid+1,r,RSON); pushup(rt); } void update(int l,int r,int c,int rt){ if(l<=LSIDE(rt)&&RSIDE(rt)<=r){ DATA(rt)=c; return; } int mid=LSIDE(rt)+RSIDE(rt)>>1; if(l<=mid)update(l,r,c,LSON); if(mid<r)update(l,r,c,RSON); pushup(rt); } int query(int l,int r,int rt){ int ans=0; if(l<=LSIDE(rt)&&RSIDE(rt)<=r)return DATA(rt); int mid=LSIDE(rt)+RSIDE(rt)>>1; if(l<=mid)ans=max(ans,query(l,r,LSON)); if(mid<r)ans=max(ans,query(l,r,RSON)); return ans; } void kruskal(){ int s=0; for(int i=1;i<=m&&s<n-1;i++) if(find(g[i].u)!=find(g[i].v)){ uniun(g[i].u,g[i].v); add(g[i].u,g[i].v); g[i].used=true; s++; } for(int i=1;i<=n;i++) if(!deep[i]){ deep[i]=1; dfs1(i); dfs2(i,i); } buildtree(1,n,1); for(int i=1;i<=m;i++) if(g[i].used){ if(deep[g[i].u]>deep[g[i].v])swap(g[i].u,g[i].v); update(id[g[i].v],id[g[i].v],g[i].w,1); } } void solve(int x,int y){ int s=0; while(top[x]!=top[y]){ if(deep[top[x]]<deep[top[y]])swap(x,y); s=max(s,query(id[top[x]],id[x],1)); x=fa[top[x]]; } if(deep[x]>deep[y])swap(x,y); if(x!=y)s=max(s,query(id[x]+1,id[y],1)); printf("%d\n",s); } void work(){ int x,y; while(q--){ x=read();y=read(); solve(x,y); } } void init(){ n=read();m=read();q=read(); for(int i=1;i<=m;i++){ g[i].u=read();g[i].v=read();g[i].w=read(); g[i].used=false; } for(int i=1;i<=n;i++)father[i]=i; sort(g+1,g+m+1,cmp); kruskal(); } int main(){ init(); work(); return 0; }