[NOIP2013] 提高组 洛谷P1967 货车运输
题目描述
A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路。每一条道路对车辆都有重量限制,简称限重。现在有 q 辆货车在运输货物, 司机们想知道每辆车在不超过车辆限重的情况下,最多能运多重的货物。
输入输出格式
输入格式:输入文件名为 truck.in。
输入文件第一行有两个用一个空格隔开的整数 n,m,表示 A 国有 n 座城市和 m 条道
路。 接下来 m 行每行 3 个整数 x、 y、 z,每两个整数之间用一个空格隔开,表示从 x 号城市到 y 号城市有一条限重为 z 的道路。意:x 不等于 y,两座城市之间可能有多条道路。
接下来一行有一个整数 q,表示有 q 辆货车需要运货。
接下来 q 行,每行两个整数 x、y,之间用一个空格隔开,表示一辆货车需要从 x 城市运输货物到 y 城市,注意:x 不等于 y。
输出格式:输出文件名为 truck.out。
输出共有 q 行,每行一个整数,表示对于每一辆货车,它的最大载重是多少。如果货
车不能到达目的地,输出-1。
输入输出样例
输入样例#1:
4 3 1 2 4 2 3 3 3 1 1 3 1 3 1 4 1 3
输出样例#1:
3 -1 3
说明
对于 30%的数据,0 < n < 1,000,0 < m < 10,000,0 < q< 1,000; 对于 60%的数据,0 < n < 1,000,0 < m < 50,000,0 < q< 1,000; 对于 100%的数据,0 < n < 10,000,0 < m < 50,000,0 < q< 30,000,0 ≤ z ≤ 100,000。
倍增求LCA,然后在两个结点到其最近公共祖先的路上找最短路,就是答案。
长度最小值也可以倍增求,但是一个个上溯好像也不会T
1 /*by SilverN*/ 2 #include<iostream> 3 #include<algorithm> 4 #include<cstring> 5 #include<cstdio> 6 #include<cmath> 7 using namespace std; 8 const int mxn=300010; 9 //bas 10 int n,m; 11 //edge 12 struct li{ 13 int u,v,dis; 14 }line[mxn]; 15 int cmp(li a,li b){ 16 return a.dis>b.dis; 17 } 18 struct node{ 19 int v,dis; 20 int next; 21 }e[mxn]; 22 int hd[mxn],cnt; 23 // 24 //bc 25 int fa[mxn]; 26 void init(){ 27 for(int i=1;i<=n;i++)fa[i]=i; 28 } 29 int find(int x){ 30 if(fa[x]==x)return x; 31 return fa[x]=find(fa[x]); 32 } 33 //tree 34 int dep[mxn]; 35 int f[mxn][20]; 36 int w[mxn][20]; 37 // 38 void add_edge(int u,int v,int dis){ 39 e[++cnt].next=hd[u];e[cnt].dis=dis;e[cnt].v=v;hd[u]=cnt; 40 e[++cnt].next=hd[v];e[cnt].dis=dis;e[cnt].v=u;hd[v]=cnt; 41 } 42 void kruskal(){ 43 int i,j; 44 int tot=1; 45 for(i=1;i<=m;i++){ 46 int x=find(line[i].u),y=find(line[i].v); 47 if(x!=y){ 48 fa[x]=y; 49 tot++; 50 add_edge(line[i].u,line[i].v,line[i].dis); 51 } 52 } 53 } 54 void dfs(int u,int fafa){ 55 dep[u]=dep[fafa]+1; 56 f[u][0]=fafa; 57 int i,j; 58 for(i=hd[u];i;i=e[i].next){ 59 int v=e[i].v; 60 if(v==fafa)continue; 61 w[v][0]=e[i].dis; 62 dfs(v,u); 63 } 64 return; 65 } 66 void solve(){ 67 int i,j; 68 for(i=1;i<=n;i++)if(!dep[i]){ 69 dep[i]=1; 70 dfs(i,0); 71 } 72 for(j=1;j<=18;j++) 73 for(i=1;i<=n;i++){ 74 f[i][j]=f[f[i][j-1]][j-1]; 75 } 76 for(j=1;j<=18;j++) 77 for(i=1;i<=n;i++){ 78 w[i][j]=min(w[i][j-1],w[f[i][j-1]][j-1]); 79 } 80 81 } 82 int LCA(int x,int y){ 83 if(dep[x]<dep[y])swap(x,y); 84 int i; 85 for(i=18;i>=0;i--)if(dep[f[x][i]]>=dep[y])x=f[x][i]; 86 if(x==y)return x; 87 for(i=18;i>=0;i--) 88 if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i]; 89 return f[x][0]; 90 } 91 int mdis(int x,int rt){ 92 int d=dep[x]-dep[rt]; 93 int res=1e9; 94 for(int i=18;i>=0;i--) 95 if((d>>i)&1){ 96 res=min(res,w[x][i]); 97 x=f[x][i]; 98 } 99 return res; 100 } 101 int main(){ 102 scanf("%d%d",&n,&m); 103 int i,j; 104 int u,v,dis; 105 for(i=1;i<=m;i++) scanf("%d%d%d",&line[i].u,&line[i].v,&line[i].dis); 106 sort(line+1,line+m+1,cmp); 107 init(); 108 kruskal(); 109 solve(); 110 int q; 111 scanf("%d",&q); 112 int x,y; 113 for(i=1;i<=q;i++){ 114 scanf("%d%d",&x,&y); 115 if(find(x)!=find(y)){ 116 printf("-1\n"); 117 continue; 118 } 119 int rt=LCA(x,y); 120 if(rt==0){ 121 printf("-1\n"); 122 continue; 123 } 124 int ans=min(mdis(x,rt),mdis(y,rt)); 125 printf("%d\n",ans); 126 } 127 return 0; 128 }
本文为博主原创文章,转载请注明出处。