P1967 货车运输(倍增LCA,生成树)
作者:互联网
题目链接:
https://www.luogu.org/problemnew/show/P1967
题目描述
A国有n座城市,编号从 1到n,城市之间有 m 条双向道路。每一条道路对车辆都有重量限制,简称限重。现在有 q 辆货车在运输货物, 司机们想知道每辆车在不超过车辆限重的情况下,最多能运多重的货物。
输入输出格式
输入格式:
第一行有两个用一个空格隔开的整数n,m,表示 AA 国有n 座城市和 m条道路。
接下来 mm行每行33个整数 x, y, z,每两个整数之间用一个空格隔开,表示从 x号城市到y号城市有一条限重为 zz的道路。注意: x 不等于 y,两座城市之间可能有多条道路 。
接下来一行有一个整数 q,表示有 q 辆货车需要运货。
接下来 q 行,每行两个整数 x、y,之间用一个空格隔开,表示一辆货车需要从 x 城市运输货物到 y 城市,注意:x 不等于 y 。
输出格式:
共有 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,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维护树上两点之间最小距离。
注意有重边和多个连通分量的情况。
#include<bits/stdc++.h> using namespace std; #define mp make_pair const int N=10010,M=50010; struct edge{ int x,y,c; }ed[M]; bool cmp(edge &a,edge &b){ return a.c>b.c; } int f[N]; int findroot(int x){ if(f[x]==x) return x; return f[x]=findroot(f[x]); } void merge(int a,int b){ int f1=findroot(a),f2=findroot(b); if(f1!=f2){ f[f1]=f2; } } int n,m; vector<pair<int,int>> a[N]; map<pair<int,int>,int > ump; int d[N],fa[N][31],v[N][31],lg[N]; void dfs(int u,int last){ d[u]=d[last]+1; v[u][0]=ump[mp(u,last)]; fa[u][0]=last; for(int i=1;i<=lg[d[u]]-1;i++){ fa[u][i]=fa[fa[u][i-1]][i-1]; v[u][i]=min(v[u][i-1],v[fa[u][i-1]][i-1]); } for(auto to:a[u]){ if(to.first!=last){ dfs(to.first,u); } } } int lca(int x,int y){ int dis=0x3f3f3f3f; if(d[x]<d[y]) swap(x,y); while(d[x]>d[y]){ dis=min(dis,v[x][lg[d[x]-d[y]]-1]); x=fa[x][lg[d[x]-d[y]]-1]; } if(x==y) return dis; for(int i=lg[d[x]]-1;i>=0;i--){ if(fa[x][i]!=fa[y][i]){ dis=min(dis,min(v[x][i],v[y][i])); x=fa[x][i]; y=fa[y][i]; } } return min(dis,min(v[x][0],v[y][0])); } int main(){ scanf("%d %d",&n,&m); for(int i=0;i<m;i++){ int x,y,c; if(x==y) continue; scanf("%d %d %d",&ed[i].x,&ed[i].y,&ed[i].c); } sort(ed,ed+m,cmp); for(int i=1;i<=n;i++){ f[i]=i; lg[i]=lg[i-1]+(1<<lg[i-1]==i);//log2(i)+1; } int cnt=0; for(int i=0;i<m;i++){ int x=ed[i].x,y=ed[i].y; int f1=findroot(x),f2=findroot(y); if(f1!=f2){ f[f1]=f2; a[x].push_back(mp(y,ed[i].c)); a[y].push_back(mp(x,ed[i].c)); ump[mp(x,y)]=ump[mp(y,x)]=ed[i].c; cnt++; if(cnt==n-1) break; } } //多个连通分量 for(int i=1;i<=n;i++){ if(f[i]==i){ ump[mp(i,0)]=0; dfs(i,0); } } int Q; scanf("%d",&Q); for(int i=1;i<=Q;i++){ int x,y; scanf("%d %d",&x,&y); if(findroot(x)!=findroot(y)) printf("-1\n"); else printf("%d\n",lca(x,y)); } return 0; }
标签:return,min,int,货车运输,fa,000,LCA,P1967,dis 来源: https://www.cnblogs.com/zhuixunfighting/p/10657973.html