星际导航
(nav.pas/c/cpp/in/out,1s,64MB)
题目描述
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。
样例输入
4 5
1 2 5
1 3 2
2 3 11
2 4 6
3 4 4
3
2 3
1 4
1 2
样例输出
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。数据不保证没有重边和自环。
这种题的模型很常见,先最小生成树,再深搜处理出fat[],next[],d[]数组,分别表示生成树后每个节点的父亲,到父亲的路径权值,和此节点的深度,然后就可以一步一步先上搜,或者LCA更新答案。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<cstring> 5 #include<cmath> 6 #include<algorithm> 7 #include<vector> 8 #include<queue> 9 #include<fstream> 10 using namespace std; 11 inline int read(){ 12 int x=0,f=1;char ch=getchar(); 13 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 14 while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} 15 return x*f; 16 } 17 int N,M,Q; 18 struct node{ 19 int x,y,w; 20 }e[300005]; 21 struct node1{ 22 int x,y; 23 }q[100005]; 24 int cmp(const node&a,const node&b){ 25 if(a.w<b.w) return 1; 26 return 0; 27 } 28 int fa[100005]; 29 int getfa(int u){ 30 if(u!=fa[u]) fa[u]=getfa(fa[u]); 31 return fa[u]; 32 } 33 vector<int>to[100005],cost[100005]; 34 inline void dfs(int,int); 35 inline int get_ans(int,int); 36 int d[100005]; 37 int fat[100005]; 38 int next[100005]; 39 int main(){ 40 //freopen("nav.in","r",stdin); 41 //freopen("nav.out","w",stdout); 42 N=read(); M=read(); 43 for(int i=1;i<=M;i++){ 44 int u,v,c; 45 u=read(); v=read(); c=read(); 46 e[i].x=u; e[i].y=v; e[i].w=c; 47 } 48 Q=read(); 49 for(int i=1;i<=Q;i++){ 50 int u,v; 51 u=read(); v=read(); 52 q[i].x=u; q[i].y=v; 53 } 54 sort(e+1,e+M+1,cmp); 55 for(int i=1;i<=N;i++) fa[i]=i; 56 for(int i=1;i<=M;i++){ 57 int u=e[i].x; int v=e[i].y; int c=e[i].w; 58 int fau=getfa(u); int fav=getfa(v); 59 if(fau!=fav){ 60 if(fau<fav) fa[fav]=fa[fau]; 61 else fa[fau]=fa[fav]; 62 to[u].push_back(v); to[v].push_back(u); 63 cost[u].push_back(c); cost[v].push_back(c); 64 } 65 } 66 for(int i=1;i<=N;i++){ 67 if(fa[i]==i){ 68 dfs(i,1); 69 break; 70 } 71 } 72 for(int i=1;i<=Q;i++){ 73 int u=q[i].x; int v=q[i].y; 74 if(getfa(u)!=getfa(v)){ 75 cout<<"impossible"<<endl; 76 continue; 77 } 78 printf("%d ",get_ans(u,v)); 79 } 80 return 0; 81 } 82 inline void dfs(int root,int deep){ 83 d[root]=deep; 84 for(int i=0;i<to[root].size();i++){ 85 int g=to[root][i]; 86 if(d[g]==0){ 87 dfs(g,deep+1); 88 fat[g]=root; 89 next[g]=cost[root][i]; 90 } 91 } 92 } 93 int get_ans(int u,int v){ 94 int x=u,y=v,ans=0; 95 while(x!=y){ 96 if(d[x]<d[y]) y=fat[y]; 97 else if(d[x]>d[y]) x=fat[x]; 98 else if(d[x]==d[y]) x=fat[x],y=fat[y]; 99 } 100 while(u!=x) ans=max(ans,next[u]),u=fat[u]; 101 while(v!=y) ans=max(ans,next[v]),v=fat[v]; 102 return ans; 103 }