• [BZOJ 3732]Network


    Description

    给你N个点的无向图 (1 <= N <= 15,000),记为:1…N。
    图中有M条边 (1 <= M <= 30,000) ,第j条边的长度为: d_j ( 1 < = d_j < = 1,000,000,000).

    现在有 K个询问 (1 < = K < = 20,000)。
    每个询问的格式是:A B,表示询问从A点走到B点的所有路径中,最长的边最小值是多少?

    Input

    第一行: N, M, K。
    第2..M+1行: 三个正整数:X, Y, and D (1 <= X <=N; 1 <= Y <= N). 表示X与Y之间有一条长度为D的边。
    第M+2..M+K+1行: 每行两个整数A B,表示询问从A点走到B点的所有路径中,最长的边最小值是多少?

    Output

     对每个询问,输出最长的边最小值是多少。

    Sample Input

    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

    5
    5
    5
    4
    4
    7
    4
    5

    HINT

    1 <= N <= 15,000
    1 <= M <= 30,000
    1 <= d_j <= 1,000,000,000
    1 <= K <= 15,000

    转载自http://www.cnblogs.com/ZegWe/p/6243883.html

    我们按照kruskal求最小生成树的方式加边,但每次在加边时,新建一个节点,然后把两个联通块(其实是两棵二叉树)的根节点作为其左右儿子,把边权赋值给新建节点。那么我们可以发现这棵树有几个性质。

    1. 是一棵二叉树(虽然这道题并没有什么卵用);
    2. 满足父节点的值大于等于儿子节点,是一个大顶堆,这是最关键的一点;
    3. 原图上任意两点间路径最长边的最小值等于其lca的值;

    这种建树的方法称作kruskal重构树。
    那么A,B的lca就是所求答案。

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 #include<algorithm>
     5 #define link LL
     6 using namespace std;
     7 struct Link
     8 {
     9   int u,v,c;
    10 }link[100001];
    11 bool cmp(Link a,Link b)
    12 {
    13   return a.c<b.c;
    14 }
    15 struct Node
    16 {
    17   int next,to;
    18 }edge[600001];
    19 int head[100001],num,fa[100001][18],dep[100001],n,m,k,pos,cnt;
    20 int set[100001],c[100001];
    21 void add(int u,int v)
    22 {
    23   num++;
    24   edge[num].next=head[u];
    25   head[u]=num;
    26   edge[num].to=v;
    27 }
    28 void dfs(int x,int pa)
    29 {int i;
    30   dep[x]=dep[pa]+1;
    31   for (i=1;i<=17;i++)
    32     fa[x][i]=fa[fa[x][i-1]][i-1];
    33   for (i=head[x];i;i=edge[i].next)
    34     {
    35       int v=edge[i].to;
    36       if (v!=pa)
    37     {
    38       fa[v][0]=x;
    39       dfs(v,x);
    40     }
    41     }
    42 }
    43 int LCA(int x,int y)
    44 {int i;
    45   if (dep[x]<dep[y]) swap(x,y);
    46   for (i=17;i>=0;i--)
    47     if ((1<<i)<=dep[x]-dep[y]) x=fa[x][i];
    48   if (x==y) return x;
    49   for (i=17;i>=0;i--)
    50     {
    51       if (fa[x][i]!=fa[y][i])
    52     {
    53       x=fa[x][i];
    54       y=fa[y][i];
    55     }
    56     }
    57   x=fa[x][0];y=fa[y][0];
    58   return x;
    59 }
    60 int find(int x)
    61 {
    62   if (set[x]!=0) set[x]=find(set[x]);
    63   if (set[x]==0) return x;
    64   else return set[x];
    65 }
    66 int main()
    67 {int i,x,y;
    68   cin>>n>>m>>k;
    69   for (i=1;i<=m;i++)
    70     {
    71       scanf("%d%d%d",&link[i].u,&link[i].v,&link[i].c);
    72     }
    73   sort(link+1,link+m+1,cmp);
    74   pos=n;cnt=0;
    75   for (i=1;i<=m;i++)
    76     {
    77       int p=find(link[i].u);
    78       int q=find(link[i].v);
    79       if (p!=q)
    80     {
    81       c[++pos]=link[i].c;
    82       add(p,pos);
    83       add(pos,p);
    84       add(q,pos);
    85       add(pos,q);
    86       set[p]=set[q]=pos;
    87       ++cnt;
    88       if (cnt==n-1) break;
    89     }
    90     }
    91   dfs(pos,0);
    92   while (k--)
    93     {
    94       scanf("%d%d",&x,&y);
    95       printf("%d
    ",c[LCA(x,y)]);
    96     }
    97 }
  • 相关阅读:
    LeetCode OJ-- Interleaving String **@
    二叉树遍历 Morris
    LeetCode OJ--Binary Tree Zigzag Level Order Traversal *
    LeetCode OJ-- Letter Combinations of a Phone Number ***
    【转】 堆和栈的区别
    LeetCode OJ-- Valid Sudoku
    LeetCode OJ--Word Break II ***@
    LeetCode OJ-- Surrounded Regions **@
    add host bat
    SP2013 SP1(kb28805502)补丁安装测试初体验
  • 原文地址:https://www.cnblogs.com/Y-E-T-I/p/7641717.html
Copyright © 2020-2023  润新知