gym 101081 gym F. Auction of Services 最小生成树+倍增LCA
It is becoming more common to use strategies based on social networks for shopping, contract services, arrange meetings, etc. Such strategies often involve interesting mathematical knowledge, like Game Theory. A new trend has appeared, the use of social networks to carry out virtual auctions to contract services. The service providers have agreements between them that enforce a service to cost a predetermine value. The prices a company charges, when it works in collaboration with each of its partners, can be very different, since many factors such as location, previous partnerships, tradition, etc. influence the convenience of a particular partnership.
In this problem you want to estimate the price of a service given by a couple of service providers. It is already known the price of the service given by some companies that have an agreement to work together. Furthermore, if we have two companies A and B, we can contract a service (offered by them) using a chain of companies c1, c2, ... ck, such that
- ci and ci + 1 have an agreement, for i = 1, ..., k - 1,
- c1 = A and ck = B.
Also, we know that the price to contract such chain of companies, is the highest price of a service given by a pair of adjacent companies in that chain. That's the power of social networks!
![](http://codeforces.com/predownloaded/d9/96/d996817b3dd56e5885caf3e60251983ff8cc4687.png)
In the previous figure, despite the fact that the price of the agreement between A and C is 13, the best price (in the network that links these companies) is 9, using the agreements through B.
Your task is to help these virtual auctions. The person interested in contracting a certain service chooses a pair of companies he want to contract, and you need to make a program that answers the minimum possible price of that service.
The first line contains two integers N and M, the number of companies and agreements, respectively. The companies are numbered from 1 to N. Each of the following M lines contains three integers, the ith contains Ai, Bi and Ci, indicating that there is an agreement between companies Ai and Bi whose price is Ci. Each pair of companies has at most one agreement. It is guaranteed it is possible to contract a service between any pair of companies.
The next line contains an integer Q, the number of queries. The following Q lines contain a pair of integers representing the companies which we want to contract.
Limits
- 2 ≤ N ≤ 105
- 1 ≤ M ≤ 2·105
- 1 ≤ Ai ≠ Bi ≤ N
- 1 ≤ Ci ≤ 106
- 1 ≤ Q ≤ 2·105
Print Q integers representing the price of the service for each query.
4 4
1 2 6
1 3 1
2 4 2
3 4 2
2
1 2
1 4
2
2
4 4
1 2 1
2 3 7
2 4 3
3 4 4
4
1 3
1 4
3 2
4 2
4
3
4
3
题意:无向带权图,找一个点到另一个点的边权最大值最小;
思路:最小生成树:要在n个城市之间铺设光缆,主要目标是要使这 n 个城市的任意两个之间都可以通信,但铺设光缆的费用很高,且各个城市之间铺设光缆的费用不同,因此另一个目标是要使铺设光缆的总费用最低。这就需要找到带权的最小生成树。
显然先构造一颗最小生成树,然后类似LCA的求法求两个点之间的最大值;
#pragma comment(linker, "/STACK:1024000000,1024000000") #include<iostream> #include<cstdio> #include<cmath> #include<string> #include<queue> #include<algorithm> #include<stack> #include<cstring> #include<vector> #include<list> #include<bitset> #include<set> #include<map> #include<time.h> using namespace std; #define LL long long #define bug(x) cout<<"bug"<<x<<endl; const int N=1e5+10,M=2e6+10,inf=1e9+10; const LL INF=1e18+10,mod=998244353,MOD=998244353; const double eps=1e-8,pi=(4*atan(1.0)); struct is { int u,v,w; bool operator <(const is &c)const { return w<c.w; } }a[N<<1]; int faT[N]; int Find(int x) { return x==faT[x]?x:faT[x]=Find(faT[x]); } vector<pair<int,int> >edge[N]; int fa[N][20],ma[N][20],deep[N]; void dfs(int u,int fat) { for (int i=1; i<=18 ;i++) { if(deep[u]<(1<<i)) break; fa[u][i] = fa[fa[u][i-1]][i-1]; ma[u][i] = max(ma[fa[u][i-1]][i-1],ma[u][i-1]); } for (int i=0;i<edge[u].size();i++) { int v=edge[u][i].first; int w=edge[u][i].second; if(v==fat) continue; deep[v]=deep[u]+1; fa[v][0]=u; ma[v][0]=w; dfs(v,u); } } int RMQ_LCA(int x,int y) { if(deep[x]<deep[y]) swap(x,y); int d=deep[x]-deep[y],ans=0; for (int i=0; i<=18 ;i++) if((1<<i)&d) ans=max(ans,ma[x][i]),x=fa[x][i]; for (int i=18; i>=0 ;i--) { if(fa[x][i]!=fa[y][i]) { ans=max(ans,ma[x][i]),ans=max(ans,ma[y][i]); x=fa[x][i];y=fa[y][i]; } } if(x==y) return ans; else return max(ans,max(ma[y][0],ma[x][0])); } int main() { int n,m; scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) faT[i]=i; for(int i=1;i<=m;i++) scanf("%d%d%d",&a[i].u,&a[i].v,&a[i].w); sort(a+1,a+1+m); for(int i=1;i<=m;i++) { int x=Find(a[i].u); int z=Find(a[i].v); if(x!=z) { edge[a[i].u].push_back(make_pair(a[i].v,a[i].w)); edge[a[i].v].push_back(make_pair(a[i].u,a[i].w)); faT[x]=z; } } dfs(1,0); int q; scanf("%d",&q); while(q--) { int u,v; scanf("%d%d",&u,&v); printf("%d\n",RMQ_LCA(u,v)); } return 0; }