zoukankan      html  css  js  c++  java
  • P1967 货车运输

    P1967 货车运输

    思路:

        将边权从大到小排序,然后建立最大生成树,在新图上求两个点的lca即可

      1 #include <cstdio>
      2 #include <iostream>
      3 #include <cstring>
      4 #include <algorithm>
      5 #include <cmath>
      6 #include <cctype>
      7 using namespace std;
      8 
      9 #define inf 0x7f7f7f7f
     10 #define LL long long
     11 #define res register int
     12 inline int read()
     13 {
     14     int x(0),f(1); char ch;
     15     while(!isdigit(ch=getchar())) if(ch=='-') f=-1;
     16     while(isdigit(ch)) x=x*10+ch-'0',ch=getchar();
     17     return f*x;
     18 }
     19 int n,m;
     20 const int N=500000+5;
     21 int head[N],nxt[N<<1],ver[N<<1],edge[N<<1],tot;
     22 struct E{
     23     int u,v,w;
     24 }e[N];
     25 int vis[N],fa[N],d[N];
     26 int f[N][22],dis[N][22];
     27 
     28 //inline int min(int a,int b){return a<b?a:b;}
     29 inline bool cmp(E a,E b) {return a.w>b.w;}
     30 inline void add(int x,int y,int z) {
     31     ver[++tot]=y; nxt[tot]=head[x]; head[x]=tot; edge[tot]=z;
     32     ver[++tot]=x; nxt[tot]=head[y]; head[y]=tot; edge[tot]=z;
     33 }    
     34 //inline void swap(int &x,int &y) {int tmp=x; x=y; y=tmp;}
     35 inline int get(int x) {
     36     if(x==fa[x]) return x; return fa[x]=get(fa[x]);
     37 }
     38 
     39 inline void Kruskal()
     40 {
     41     sort(e+1,e+m+1,cmp);
     42     for(res i=1 ; i<=n ; i++) fa[i]=i;
     43     for(res i=1 ; i<=m ; i++)
     44     {
     45         int x=get(e[i].u),y=get(e[i].v),z=e[i].w;
     46         if(x==y) continue;
     47         fa[x]=y;
     48         add(x,y,z);
     49     }
     50 }
     51 
     52 void dfs(int x)
     53 {
     54     vis[x]=1;
     55     for(res i(head[x]) ; i ; i=nxt[i])
     56     {
     57         int y=ver[i]; 
     58         if(vis[y]) continue;
     59         f[y][0]=x; dis[y][0]=edge[i];
     60 //        printf("dis %d",dis[y][0]);
     61         d[y]=d[x]+1;    dfs(y);
     62     }
     63 }
     64 
     65 inline int lca(int x,int y)
     66 {
     67     if(get(x)!=get(y)) return -1;
     68     if(d[x]<d[y]) swap(x,y);
     69     int ans=inf;
     70     for(res i=20 ; i>=0 ; i--)
     71         if(d[f[x][i]]>=d[y])
     72         {
     73             ans=min(ans,dis[x][i]);    
     74             x=f[x][i];
     75         } 
     76     if(x==y) return ans;
     77     for(res i=20 ; i>=0 ; i--)
     78         if(f[x][i]!=f[y][i])
     79         {
     80             ans=min(ans,dis[x][i]);
     81             ans=min(ans,dis[y][i]);
     82             x=f[x][i],y=f[y][i];
     83         }
     84     ans=min(ans,dis[x][0]);
     85     ans=min(ans,dis[y][0]);
     86     return ans;
     87 }
     88 
     89 
     90 int main()
     91 {
     92 //    freopen("in.txt","r",stdin);
     93     n=read(); m=read();
     94     for(res i=1 ; i<=m ; i++) 
     95         e[i].u=read(), e[i].v=read(),e[i].w=read();
     96     Kruskal();
     97     for(res i=1 ; i<=n ; i++)
     98     {
     99         if(!vis[i]) 
    100         {
    101             d[i]=1; dfs(i);
    102             f[i][0]=i; dis[i][0]=inf;    
    103         }
    104     }
    105     //注意顺序
    106     for(int i=1; i<=20; i++)
    107         for(int j=1; j<=n; j++){
    108             f[j][i]=f[f[j][i-1]][i-1]; 
    109             dis[j][i]=min(dis[j][i-1], dis[f[j][i-1]][i-1]);
    110         }
    111     int q=read();
    112     for(res i=1 ; i<=q ; i++)
    113     {
    114         int x=read(),y=read();
    115         printf("%d
    ",lca(x,y));
    116     }
    117     return 0;
    118 }
    View Code
  • 相关阅读:
    内存池(MemPool)技术详解
    关于项目时间管理的六点须知
    如何与你的老大沟通?
    一个简单的面试题
    Windows下的Memcache安装与测试教程
    反向代理服务器的工作原理
    Linux下的Memcache安装方法
    TCP/IP协议详解
    浅谈负载均衡技术与分类
    MySQL数据备份和恢复的方法大全
  • 原文地址:https://www.cnblogs.com/wmq12138/p/10380953.html
Copyright © 2011-2022 走看看