题目描述
AA国有nn座城市,编号从 1到n,城市之间有m 条双向道路。每一条道路对车辆都有重量限制,简称限重。现在有 q 辆货车在运输货物, 司机们想知道每辆车在不超过车辆限重的情况下,最多能运多重的货物。
输入输出格式
输入格式:
第一行有两个用一个空格隔开的整数n,m,表示 A 国有 n 座城市和 m 条道路。
接下来 m行每行3个整数 x,y,z,每两个整数之间用一个空格隔开,表示从 xx号城市到yy号城市有一条限重为 z的道路。注意:x 不等于 y,两座城市之间可能有多条道路 。
接下来一行有一个整数 q,表示有 q 辆货车需要运货。
接下来 q 行,每行两个整数 x、y,之间用一个空格隔开,表示一辆货车需要从 x 城市运输货物到 y 城市,注意: x 不等于 y 。
输出格式:
共有 q 行,每行一个整数,表示对于每一辆货车,它的最大载重是多少。如果货车不能到达目的地,输出-1。
输入输出样例
说明
对于 30%的数据,0 < n < 1,000,0 < m < 10,000,0 < q< 1,0000<n<1,000,0<m<10,000,0<q<1,000;
对于 60%的数据,0 < n < 1,000,0 < m < 50,000,0 < q< 1,0000<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,0000<n<10,000,0<m<50,000,0<q<30,000,0≤z≤100,000。
--------------------------------------------------------------------
这道题的思路就是先用最大生成树将图跑成一棵新树,然后在跑LCA的时候更新路上的最小值
为什么呢,“我们可以发现有一些权值较小的边是不会被走过的。正如样例中的第三条边,就算有其他的很多条边,这条边无论如何也是不会被走过的。于是我们想到了可以将图中这样的边去掉,按照这个思路我们便想到了构造最大生成树,将其余的边去除。”(来自luogu的大佬
然后我的关注点就变为了如何在LCA上记录最小值呢?
在预处理每个点的父亲的时候 我们用一个相似的f[i][j]数组来记录i跳2^j时的最小边权
注意:LCA在开数组的时候,maxn=20, 则p[N][maxn+5] (这个错查了2h....以后绝对不能再犯了
1 #include<bits/stdc++.h> 2 #define N 100010 3 #define maxn 20 4 #define INF 0x7f7f7f7f 5 #define ll long long 6 using namespace std; 7 int n,m,q; 8 struct node 9 { 10 int u,v,nxt; 11 ll w; 12 }e[N*2],d[N*2]; 13 int first[N],cnt; 14 void ade(int u,int v,ll w) 15 { 16 e[++cnt].nxt=first[u]; first[u]=cnt; 17 e[cnt].u=u; e[cnt].v=v; e[cnt].w=w; 18 } 19 20 int fir[N],cnnt; 21 void adde(int u,int v,ll w) 22 { 23 d[++cnnt].nxt=fir[u]; fir[u]=cnnt; 24 d[cnnt].u=u; d[cnnt].v=v; d[cnnt].w=w; 25 } 26 /*-------kruskal---------*/ 27 int fa[N]; 28 int la(int x) 29 { 30 if(fa[x]!=x) fa[x]=la(fa[x]); 31 return fa[x]; 32 } 33 bool cmp(node a,node b) 34 { 35 return a.w>b.w; 36 } 37 void kruskal() 38 { 39 for(int i=1;i<=n;i++) fa[i]=i; 40 sort(e+1,e+cnt+1,cmp); 41 for(int i=1;i<=cnt;i++) 42 { 43 int x=la(e[i].u),y=la(e[i].v); 44 if(x!=y) 45 { 46 fa[x]=y; 47 adde(e[i].u,e[i].v,e[i].w); 48 adde(e[i].v,e[i].u,e[i].w); 49 } 50 } 51 // cout<<"!!!!"; 52 // for(int i=1;i<=cnnt;i+=2) 53 // printf("%d %d %d\n",d[i].u,d[i].v,d[i].w); 54 // cout<<"!!!!"; 55 } 56 57 /*-----lca------*/ 58 int dep[N],p[N][maxn+5]; 59 ll val[N][maxn+5]; 60 bool vis[N]; 61 void pre() 62 { 63 for(int j=1;j<=maxn;j++) 64 for(int i=1;i<=n;i++) 65 { 66 p[i][j]=p[p[i][j-1]][j-1]; 67 val[i][j]=min(val[i][j-1],val[p[i][j-1]][j-1]); 68 } 69 } 70 void dfs(int u,int fath) 71 { 72 vis[u]=1; 73 dep[u]=dep[fath]+1; 74 p[u][0]=fath; 75 for(int i=fir[u];i;i=d[i].nxt) 76 { 77 int v=d[i].v; 78 if(vis[v]) continue; 79 val[v][0]=d[i].w; 80 dfs(v,u); 81 } 82 } 83 ll lca(int x,int y) 84 { 85 ll minx=INF; 86 if(dep[x]<dep[y]) swap(x,y); 87 for(int i=maxn;i>=0;i--) 88 if(dep[x]-(1<<i)>=dep[y]) 89 { 90 minx=min(minx,val[x][i]); 91 x=p[x][i]; 92 } 93 if(x==y) return minx; 94 for(int i=maxn;i>=0;i--) 95 if(p[x][i]!=p[y][i]) 96 { 97 minx=min( minx, min(val[x][i],val[y][i]) ); 98 x=p[x][i],y=p[y][i]; 99 } 100 minx=min( minx, min(val[x][0],val[y][0]) ); 101 return minx; 102 } 103 /*---------*/ 104 int main() 105 { 106 scanf("%d%d",&n,&m); 107 memset(val,INF,sizeof(val)); 108 for(int i=1,x,y;i<=m;i++) 109 { 110 ll z; 111 scanf("%d%d%lld",&x,&y,&z); 112 ade(x,y,z); 113 } 114 kruskal(); 115 for(int i=1;i<=n;i++) 116 if(!vis[i]) dfs(i,0); 117 pre(); 118 scanf("%d",&q); 119 while(q--) 120 { 121 int x,y; 122 scanf("%d%d",&x,&y); 123 if(la(x)!=la(y)) printf("-1\n"); 124 else printf("%lld\n",lca(x,y)); 125 } 126 return 0; 127 } 128 /* 129 10 24 130 4 7 19038 131 7 10 7375 132 7 9 17853 133 9 8 6341 134 7 2 16976 135 10 3 2835 136 10 4 19285 137 9 4 29193 138 3 4 4852 139 3 8 16597 140 9 1 4138 141 9 7 21611 142 7 4 10586 143 10 4 7821 144 10 9 25636 145 3 9 28425 146 2 3 17229 147 4 8 11331 148 9 2 25053 149 6 4 929 150 8 3 1738 151 10 9 28542 152 1 2 28343 153 3 5 13215 154 9 155 7 5 156 2 4 157 10 2 158 5 10 159 7 10 160 4 3 161 10 1 162 10 4 163 8 4 164 165 */ 166 /* 167 13215 168 25053 169 25053 170 13215 171 21611 172 28425 173 25053 174 28542 175 16597 176 */