题目描述
sideman做好了回到Gliese 星球的硬件准备,但是sideman的导航系统还没有完全设计好。为了方便起见,我们可以认为宇宙是一张有N 个顶点和M 条边的带权无向图,顶点表示各个星系,两个星系之间有边就表示两个星系之间可以直航,而边权则是航行的危险程度。
sideman 现在想把危险程度降到最小,具体地来说,就是对于若干个询问(A, B),sideman 想知道从顶点A 航行到顶点B 所经过的最危险的边的危险程度值最小可能是多少。作为sideman 的同学,你们要帮助sideman 返回家园,兼享受安全美妙的宇宙航行。所以这个任务就交给你了。
输入输出格式
输入格式:
第一行包含两个正整数N 和M,表示点数和边数。
之后 M 行,每行三个整数A,B 和L,表示顶点A 和B 之间有一条边长为L 的边。顶点从1 开始标号。
下面一行包含一个正整数 Q,表示询问的数目。
之后 Q 行,每行两个整数A 和B,表示询问A 和B 之间最危险的边危险程度的可能最小值。
输出格式:
对于每个询问, 在单独的一行内输出结果。如果两个顶点之间不可达, 输出impossible。
输入输出样例
输入样例#1:
4 5
1 2 5
1 3 2
2 3 11
2 4 6
3 4 4
3
2 3
1 4
1 2
输出样例#1:
5
4
5
说明
对于40% 的数据,满足N≤1000,M≤3000,Q≤1000。
对于 80% 的数据,满足N≤10000,M≤105,Q≤1000。
对于 100% 的数据,满足N≤105,M≤3×105,Q≤105,L≤109。数据不保证没有重边和自环。
实际上,更快的做法是使用Kruskal重构树!
#include<algorithm> #include<iostream> #include<cstdio> #include<cctype> using namespace std; inline int rd(){ int ret=0,f=1;char c; while(c=getchar(),!isdigit(c))f=c=='-'?-1:1; while(isdigit(c))ret=ret*10+c-'0',c=getchar(); return ret*f; } const int MAXN = 200005; const int M = 600005; int tot,rt; int val[MAXN]; inline int newnode(){return ++tot;} struct Undirected_Edge{ int x,y,w; bool operator <(const Undirected_Edge &rhs){ return w<rhs.w; } }edges[M<<1]; int n,m,q; struct Edge{ int next,to; }e[MAXN<<1]; int ecnt,head[MAXN]; inline void add(int x,int y){ e[++ecnt].to = y; e[ecnt].next = head[x]; head[x] = ecnt; } int fa[MAXN],dep[MAXN],siz[MAXN],hch[MAXN]; void dfs1(int cur,int pre){ fa[cur]=pre;dep[cur]=dep[pre]+1;siz[cur]=1; int mx=-1; for(int i=head[cur];i;i=e[i].next){ int v=e[i].to; if(v==pre) continue; dfs1(v,cur); siz[cur]+=siz[v]; if(siz[v]>mx) hch[cur]=v,mx=siz[v]; } } int top[MAXN]; void dfs2(int cur,int tp){ top[cur]=tp; if(hch[cur]) dfs2(hch[cur],tp); for(int i=head[cur];i;i=e[i].next){ int v=e[i].to; if(v==fa[cur]||v==hch[cur]) continue;// dfs2(v,v); } } int lca(int x,int y){ while(top[x]!=top[y]){ dep[top[x]]>=dep[top[y]]?x=fa[top[x]]:y=fa[top[y]]; } return dep[x]<=dep[y]?x:y; } struct ufs{ int fa[MAXN]; int fnd(int x){return x==fa[x]?x:fa[x]=fnd(fa[x]);} void cat(int x,int y){x=fnd(x);y=fnd(y);if(x==y)return;fa[x]=y;} }U; int main(){ n=rd();m=rd(); int x,y,w,u,v,cur;tot=n; for(int i=1;i<=n*2;i++) U.fa[i]=i; for(int i=1;i<=m;i++){ edges[i].x = rd(); edges[i].y = rd(); edges[i].w = rd(); } sort(edges+1,edges+1+m); int edge_cnt=0; for(int i=1;i<=m;i++){ x=edges[i].x,y=edges[i].y,w=edges[i].w; u=U.fnd(x);v=U.fnd(y); if(u==v)continue; edge_cnt++; cur=newnode(); U.cat(u,cur);U.cat(v,cur); val[cur]=w; add(u,cur);add(v,cur); add(cur,u);add(cur,v); if(edge_cnt==n-1)break; } for(int i=1;i<=tot;i++){ if(siz[i])continue; v=U.fnd(i); dfs1(v,0);dfs2(v,v); } q=rd(); for(int i=1;i<=q;i++){ x=rd();y=rd(); if(U.fnd(x)!=U.fnd(y)) {puts("impossible");continue;} printf("%d\n",val[lca(x,y)]); } return 0; }