lh的简单图论

lh的简单图论

http://10.64.70.166/problem/1112

lh的简单图论
 

Description

 

众所周知,集训队的lh同学txdy,有一天他在写着代码,突然哼起了raprap,哟,哟哟,你看这个碗它又大又圆,就像这个题它又短又难,skrskr,skrskr。

lhlh在着手解决一个图论的问题:

已知有一个nn个点的无向图,图中有mm条边,每条边的权值为w_iwi

lhlh想知道,他从点aa走到点bb,所走的最长的边长最小值是多少?

 

Input

 

第一行输入三个正整数n,m,qn,m,q,分别表示有nn个点mm条边和qq次询问。

接下来mm行,每行有三个数分别为u_iuiv_iviw_iwi表示从点uu到点vv有一条路径边长为ww。

接下来qq行,每行有两个数aa,bb,表示lhlh想知道他从aa走到bb所走的最长的边长的最小值。

 

Output

 

输出qq行,每行一个正整数,表示他从点aa走到点bb,所走的最长的边长最小值是多少。

 

Sample Input 1 

6 6 8 
1 2 5 
2 3 4 
3 4 3 
1 4 8 
2 5 7 
4 6 2 
1 2 
1 3 
1 4 
2 3 
2 4 
5 1 
6 2 
6 1 

Sample Output 1

5 
5 
5 
4 
4 
7 
4 
5 

Hint

1n15000

1M30000

1wi1000000000

1q20000

 

 

这个题目就是比较典型的图转树,这个好像就是UVA的11354

你要用最小生成树把图转变成树,然后再用LCA处理这棵树

 

#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <string>
#include <cmath>
#include <algorithm>
#include <queue>
#include <iostream>
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int maxn = 3e4 + 100;
int dp[maxn][30];
ll gw[maxn][30];
int deep[maxn];
int n, m, q, N;
struct node
{
    int from,to;
    ll dist;
    node(int from=0,int to=0,ll dist=0):from(from),to(to),dist(dist){}
}exa[maxn];
vector<node>vec[maxn];
int f[maxn];
int findx(int x)
{
    return f[x] == x ? x : f[x] = findx(f[x]);
}

void unite(int x,int y)
{
    x = findx(x);
    y = findx(y);
    if (x == y) return;
    f[x] = y;
}

bool same(int x,int y)
{
    return findx(x) == findx(y);
}
bool cmp(node a,node b)
{
    return a.dist < b.dist;
}

void dfs(int s)
{
    for(int i=1;i<=N;i++)
    {
        dp[s][i] = dp[dp[s][i - 1]][i - 1];
        gw[s][i] = max(gw[s][i - 1], gw[dp[s][i - 1]][i - 1]);
    }
    int len = vec[s].size();
    for(int i=0;i<len;i++)
    {
        node e = vec[s][i];
        if(e.to!=dp[s][0])
        {
            deep[e.to] = deep[s] + 1;
            dp[e.to][0] = s;
            gw[e.to][0] = e.dist;
            dfs(e.to);
        }
    }
}

ll LCA(int x,int y)
{
    if (x == y) return 0;
    if (deep[x] > deep[y]) swap(x, y);
    ll ans = 0;
    for(int i=N;i>=0;i--)//抬到同一高度
    {
        if(deep[x]<deep[y]&&deep[dp[y][i]]>=deep[x])
        {
            ans = max(ans, gw[y][i]);
            y = dp[y][i];
        }
    }
    for(int i=N;i>=0;i--)//一起往上走
    {
        if(dp[x][i]!=dp[y][i])
        {
            ans = max(ans, gw[x][i]);
            ans = max(ans, gw[y][i]);
            x = dp[x][i];
            y = dp[y][i];
        }
    }
    if(x!=y)//最后一步
    {
        ans = max(ans, gw[x][0]);
        ans = max(ans, gw[y][0]);
    }
    return ans;
}

int main()
{
    cin >> n >> m >> q;
    for(int i=1;i<=m;i++)
    {
        int a, b;
        ll w;
        cin >> a >> b >> w;
        exa[i] = node(a, b, w);
    }
    for (int i = 1; i <= n; i++) f[i] = i;
    sort(exa + 1, exa + 1 + m, cmp);
    for(int i=1;i<=m;i++)
    {
        int x = exa[i].from, y = exa[i].to;
        if (same(x, y)) continue;
        unite(x,y);
        vec[x].push_back(node(x, y, exa[i].dist));
        vec[y].push_back(node(y, x, exa[i].dist));
    }
    N = (log(n + 0.0)) / log(2.0);
    deep[1] = 0;
    dfs(1);
    for(int i=1;i<=q;i++)
    {
        int x, y;
        cin >> x >> y;
        ll ans = LCA(x, y);
        cout << ans << endl;
    }
    return 0;
}

 

posted @ 2019-09-07 00:00  EchoZQN  阅读(216)  评论(0编辑  收藏  举报