codevs 1519 过路费 最小生成树+倍增

/*codevs 1519 过路费 最小生成树+倍增*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 100010
#define inf 0x3f3f3f3
using namespace std;
int n,m,q,num,head[maxn],fa[maxn][25],mx[maxn][25],c[maxn],father[maxn];
struct node{
    int v,t,pre;
}e[maxn*2];
struct edge{
    int u,v,t;
    bool operator < (const edge &x) const {
        return t<x.t;
    }
}p[maxn];
int init(){
    int x=0,f=1;char s=getchar();
    while(s<‘0‘||s>‘9‘){if(s==‘-‘)f=-1;s=getchar();}
    while(s>=‘0‘&&s<=‘9‘){x=x*10+s-‘0‘;s=getchar();}
    return x*f;
}
int max(int x,int y){
    return x>y?x:y;
}
void swap(int &x,int &y){
    int z=x;x=y;y=z;
}
int find(int x){
    if(father[x]!=x)father[x]=find(father[x]);
    return father[x];
}
void Add(int from,int to,int dis){
    num++;e[num].v=to;
    e[num].t=dis;
    e[num].pre=head[from];
    head[from]=num;
}
void Dfs(int now,int from,int dep,int D){
    fa[now][0]=from;c[now]=dep;mx[now][0]=D;
    for(int i=head[now];i;i=e[i].pre){
        int v=e[i].v;
        if(v==from)continue;
        Dfs(v,now,dep+1,e[i].t);
    }
}
void Get_fa(){
    for(int j=1;j<=20;j++)
        for(int i=1;i<=n;i++){
            fa[i][j]=fa[fa[i][j-1]][j-1];
            mx[i][j]=max(mx[i][j-1],mx[fa[i][j-1]][j-1]);
        }
}
int LCA(int a,int b){
    int ret=0;
    if(c[a]<c[b])swap(a,b);
    int t=c[a]-c[b];
    for(int i=0;i<=20;i++)
        if(t&(1<<i)){
            ret=max(ret,mx[a][i]);
            a=fa[a][i];
        }
    if(a==b)return ret;
    for(int i=20;i>=0;i--)
        if(fa[a][i]!=fa[b][i]){
            ret=max(ret,mx[a][i]);
            ret=max(ret,mx[b][i]);
            a=fa[a][i];b=fa[b][i];
        }
    ret=max(ret,mx[a][0]);//是mx不是fa!!
    ret=max(ret,mx[b][0]);
    return ret;
}
int main()
{
    n=init();m=init();
    int u,v,t;
    for(int i=1;i<=n;i++)
        father[i]=i;
    for(int i=1;i<=m;i++){
        p[i].u=init();p[i].v=init();p[i].t=init();
    }
    sort(p+1,p+1+m);
    int tot=0;
    for(int i=1;i<=m;i++){
        int r1=find(p[i].u);
        int r2=find(p[i].v);
        if(r1!=r2){
            father[r2]=r1;tot++;
            Add(p[i].u,p[i].v,p[i].t);
            Add(p[i].v,p[i].u,p[i].t);
        }
        if(tot==n-1)break;
    }
    Dfs(1,0,0,0);Get_fa();
    q=init();
    while(q--){
        u=init();v=init();
        t=LCA(u,v);
        printf("%d\n",t);
    }
    return 0;
}
时间: 2024-10-10 02:15:12

codevs 1519 过路费 最小生成树+倍增的相关文章

codevs 1519 过路费

这个和货车运输没有区别...只不过换成了最小生成树. #include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<cmath>#define maxv 40005#define maxe 200005#define maxq 30005using namespace std;int n,m,x,y,z,anc[maxv][20],ma[maxv][2

习题:codevs 1519 过路费

今天拿了这道题目练练手,感觉自己代码能力又增强了不少: 我的思路跟别人可能不一样. 首先我们很容易就能看出,我们需要的边就是最小生成树算法kruskal算法求出来的边,其余的边都可以删掉,于是就有了这个kruskal选边建图的过程. 1 struct kruskalsolve{ 2 int l,r,w; 3 }kr[maxm];此处省略的内容接下来会有给出全部代码 4 int find(int x){ 5 if(f[x] != x)f[x] = find(f[x]); 6 return f[x]

1519 过路费

1519 过路费 时间限制: 1 s 空间限制: 256000 KB 题目等级 : 大师 Master 题解 题目描述 Description 在某个遥远的国家里,有 n个城市.编号为 1,2,3,…,n.这个国家的政府修建了m 条双向道路,每条道路连接着两个城市.政府规定从城市 S 到城市T需要收取的过路费为所经过城市之间道路长度的最大值.如:A到B长度为 2,B到C 长度为3,那么开车从 A经过 B到C 需要上交的过路费为 3.    佳佳是个做生意的人,需要经常开车从任意一个城市到另外一个

【bzoj4242】水壶 BFS+最小生成树+倍增LCA

题目描述 JOI君所居住的IOI市以一年四季都十分炎热著称. IOI市是一个被分成纵H*横W块区域的长方形,每个区域都是建筑物.原野.墙壁之一.建筑物的区域有P个,编号为1...P. JOI君只能进入建筑物与原野,而且每次只能走到相邻的区域中,且不能移动到市外. JOI君因为各种各样的事情,必须在各个建筑物之间往返.虽然建筑物中的冷气设备非常好,但原野上的日光十分强烈,因此在原野上每走过一个区域都需要1单位的水.此外,原野上没有诸如自动售货机.饮水处之类的东西,因此IOI市的市民一般都携带水壶出

HDU 4081 Qin Shi Huang&#39;s National Road System 最小生成树+倍增求LCA

原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=4081 Qin Shi Huang's National Road System Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 5428    Accepted Submission(s): 1902 Problem Description

【CodeForces】827 D. Best Edge Weight 最小生成树+倍增LCA+并查集

[题意]给定n个点m条边的带边权无向连通图,对每条边求最大边权,满足其他边权不变的前提下图的任意最小生成树都经过它.n,m<=2*10^5,1<=wi<=10^9. [算法]最小生成树+倍增LCA+并查集 [题解]首先求出图的一个最小生成树,则所有边分成树边和非树边. 对于非树边(u,v),假设u和v在最小生成树上的路径的最大边权Max,那么一定满足w(u,v)<=Max /////////////////////////////////////// 原文地址:https://ww

训练指南 UVA - 11354(最小生成树 + 倍增LCA)

layout: post title: 训练指南 UVA - 11354(最小生成树 + 倍增LCA) author: "luowentaoaa" catalog: true mathjax: true tags: - 最小生成树 - LCA - 图论 - 训练指南 Bond UVA - 11354 题意 给你一张无向图,然后有若干组询问,让你输出a->b的最小瓶颈路 题解 先求出最小生成树,然后对这个最小生成树做LCA. #include<bits/stdc++.h>

bzoj3732 -- 最小生成树+倍增

显然使A到B的最长边最小的路径一定在最小生成树上,否则一定可以使生成树更小. 求出原图的最小生成树,然后用倍增求路径上最大值就可以了. 代码: 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<queue> 5 using namespace std; 6 #define N 15010 7 #define S 15 8 struct Edge{ 9 int f,t,

【51nod1743】雪之国度(最小生成树+倍增)

点此看题面 大致题意: 给你一张无向连通图,其中每条边的边权为这条边连接的两点的权值之差.每次询问两点之间是否存在两条不重复的路径,若存在则输出这两条路径上最大值的最小值. 大致思路 这题显然就是要让你维护边双. 我们可以先对原图求一遍最小生成树,然后再将其余非树边(按权值从小到大先排一次序)一条一条地加到图中. 对于这条边连接的两个点,我们需要对它们在树上路径进行修改. 要注意的是,对于已经修改过的,我们就不能对它进行再一次修改,因为边已经排过序,新加上的边肯定没有原来加上的边更优. 至于维护