/*
题目大意 给一个双向连通的图,回答若干个询问,每个询问包含一个起点s和一个终点t,
要求找到一个从s到t的路,使得路径所有边的最大危险系数最小
本题为瓶颈路
要支持快速询问,把信息组织成某种易于查询的结构
先求出最小生成树,快速求出maxcost[i][j]
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
using namespace std;
const int maxn = 50050;
const int maxm = 100010;
const int logmaxn = 20;
const int INF = 1000000000;
struct Edge
{
int from,to,w;
Edge(const int& from = 0,const int& to = 0,const int& w = 0):from(from),to(to),w(w) {}
Edge(const Edge& rsh)
{
this->from = rsh.from;
this->to = rsh.to;
this->w = rsh.w;
}
bool operator < (const Edge& rsh ) const
{
return this->w < rsh.w;
}
};
int n,m;
int root[maxn];
vector<Edge> edges;
vector<int> G[maxn],C[maxn];
// 并查集
void init_set(int n)
{
for(int i = 0 ; i < n ; i++)
{
root[i] = i;
G[i].clear();
C[i].clear();
}
}
int find_set(int x)
{
if(x != root[x])
{
root[x] = find_set(root[x]);
}
return root[x];
}
void union_set(int a,int b)
{
int x = find_set(a);
int y = find_set(b);
if(x != y)
{
root[x] = y;
}
}
void MST()
{
sort(edges.begin(),edges.end());
for(int i = 0 ; i < edges.size() ; i++)
{
int from = edges[i].from;
int to = edges[i].to;
int w = edges[i].w;
if(find_set(from) != find_set(to))
{
union_set(from,to);
G[from].push_back(to);
C[from].push_back(w);
G[to].push_back(from);
C[to].push_back(w);
}
}
}
struct LCA
{
int n;
int fa[maxn];//i的父亲编号
int cost[maxn];//i到父亲节点的距离
int L[maxn];//i节点的深度
int anc[maxn][logmaxn]; //节点i到第2^j级祖先的编号
int maxcost[maxn][logmaxn];//节点i与第2^j级祖先之间的路径上的最大权值
void preprocess() //预处理
{
for(int i = 0 ; i < n ; i++)
{
anc[i][0] = fa[i];
maxcost[i][0] = cost[i];
for(int j = 1 ; (1 << j) < n ; j++)
{
anc[i][j] = -1;
}
}
for(int j = 1 ; (1 << j) < n ; j++)
{
for(int i = 0 ; i < n ; i++)
{
if(anc[i][j-1] != -1)
{
int a = anc[i][j-1];
anc[i][j] = anc[a][j-1];
maxcost[i][j] = max(maxcost[i][j-1],maxcost[a][j-1]);
}
}
}
}
int query(int p,int q)
{
int log;
if( L[p] < L[q]) swap(p,q);
for(log = 1 ; (1 << log) <= L[p] ; log++);
log--;
int ans = -INF;
for(int i = log ; i >= 0 ; i--)
{
if(L[p] - (1<<i) >= L[q])
{
ans = max(ans,maxcost[p][i]);
p = anc[p][i];
}
}
if(p == q) // LCA 为p
{
return ans;
}
for(int i = log ; i >= 0 ; i--)
{
if(anc[p][i] != -1 && anc[p][i] != anc[q][i])
{
ans = max(ans,maxcost[p][i]);
p = anc[p][i];
ans = max(ans,maxcost[q][i]);
q = anc[q][i];
}
}
ans = max(ans,cost[p]);
ans = max(ans,cost[q]);
return ans;// LCA 为fa[p]也等于fa[q]
}
};
LCA solver;
void dfs(int u,int fa,int level)
{
solver.L[u] = level;
for(int i = 0 ; i < G[u].size() ; i++)
{
int v = G[u][i];
if(v != fa)
{
solver.fa[v] = u;
solver.cost[v] = C[u][i];
dfs(v,u,level+1);
}
}
}
void init()
{
edges.clear();
init_set(n);
}
int main()
{
#ifdef LOCAL
freopen("in.txt","r",stdin);
#endif
int kcase = 0;
while(scanf("%d %d",&n,&m) != EOF)
{
init();
int from,to,w;
for(int i = 0 ; i < m ; i++)
{
scanf("%d %d %d",&from,&to,&w);
from--;
to--;
edges.push_back(Edge(from,to,w));
}
MST();
solver.n = n;
dfs(0,-1,0);
solver.preprocess();
if(++kcase != 1) printf("\n");
int Q;
scanf("%d",&Q);
while(Q--)
{
int x,y;
scanf("%d %d",&x,&y);
printf("%d\n",solver.query(x-1,y-1));
}
}
return 0;
}
uva 11354 Bond
最新推荐文章于 2019-05-31 08:46:30 发布