zoukankan      html  css  js  c++  java
  • bzoj 3732 Network(最短路+倍增 | LCT)

    【题目链接】

        http://www.lydsy.com/JudgeOnline/problem.php?id=3732

    【题意】

        给定一个无向图,处理若干询问:uv路径上最长的边最小是多少?

    【思路一】

        最小生成树+倍增算法。

        同NOIP2013货车运输。

    【代码】

      1 #include<set>
      2 #include<cmath>
      3 #include<queue>
      4 #include<vector>
      5 #include<cstdio>
      6 #include<cstring>
      7 #include<iostream>
      8 #include<algorithm>
      9 #define trav(u,i) for(int i=front[u];i;i=e[i].nxt)
     10 #define FOR(a,b,c) for(int a=(b);a<=(c);a++)
     11 using namespace std;
     12 
     13 typedef long long ll;
     14 const int N = 1e5+10;
     15 const int M = 2e5+10;
     16 const int D = 21;
     17 const int inf = 2e9;
     18 
     19 ll read() {
     20     char c=getchar();
     21     ll f=1,x=0;
     22     while(!isdigit(c)) {
     23         if(c=='-') f=-1; c=getchar();
     24     }
     25     while(isdigit(c))
     26         x=x*10+c-'0',c=getchar();
     27     return x*f;
     28 }
     29 
     30 struct Edge { 
     31     int u,v,w,nxt;
     32     bool operator < (const Edge& rhs) const{
     33         return w<rhs.w;
     34     }
     35 }e[M];
     36 int en=1,front[N];
     37 void adde(int u,int v,int w) 
     38 {
     39     e[++en]=(Edge){u,v,w,front[u]}; front[u]=en;
     40 }
     41 vector<Edge> es;
     42 
     43 int n,m,K,p[N],_max[N][D],fa[N][D],dep[N];
     44 
     45 int ifind(int u)
     46 {
     47     return u==p[u]? u:p[u]=ifind(p[u]);
     48 }
     49 
     50 void Kruskal()
     51 {
     52     sort(es.begin(),es.end());
     53     FOR(i,0,(int)es.size()-1) {
     54         int u=es[i].u,v=es[i].v,w=es[i].w;
     55         int x=ifind(u),y=ifind(v);
     56         if(x!=y) {
     57             p[x]=y;
     58             adde(u,v,w); adde(v,u,w);
     59         }
     60     }
     61 }
     62 void dfs(int u,int father)
     63 {
     64     trav(u,i) {
     65         int v=e[i].v;
     66         if(v!=father) {
     67             fa[v][0]=u;
     68             _max[v][0]=e[i].w;
     69             dep[v]=dep[u]+1;
     70             FOR(j,1,D-1) {
     71                 fa[v][j]=fa[fa[v][j-1]][j-1];
     72                 _max[v][j]=max(_max[v][j-1],_max[fa[v][j-1]][j-1]);
     73             }
     74             dfs(v,u);
     75         }
     76     }
     77 }
     78 
     79 int query(int u,int v)
     80 {
     81     if(dep[u]<dep[v]) swap(u,v);
     82     int t=dep[u]-dep[v],ans=-inf;
     83     FOR(i,0,D-1)
     84         if(t&(1<<i)) {
     85             ans=max(ans,_max[u][i]);
     86             u=fa[u][i];
     87         }
     88     if(u==v) return ans;
     89     for(int i=D-1;i>=0;i--)
     90         if(fa[u][i]!=fa[v][i]) {
     91             ans=max(ans,max(_max[u][i],_max[v][i]));
     92             u=fa[u][i],v=fa[v][i];
     93         }
     94     ans=max(ans,max(_max[u][0],_max[v][0]));
     95     return ans;
     96 }
     97 
     98 int main()
     99 {
    100     n=read(),m=read(),K=read();
    101     FOR(i,0,n) FOR(j,0,D-1) _max[i][j]=-inf;
    102     FOR(i,1,n) p[i]=i;
    103     FOR(i,1,m) {
    104         int u=read(),v=read(),w=read();
    105         es.push_back((Edge){u,v,w,0});
    106     }
    107     Kruskal();
    108     dfs(1,-1);
    109     FOR(i,1,K) {
    110         int u=read(),v=read();
    111         printf("%d
    ",query(u,v));
    112     }
    113     return 0;
    114 }
    View Code

    【思路二】

       

        用LCT换个姿势AC。LCT维护最小生成树?

        给每条边每个点开一个LCT结点,边的maxe初始为自己,点的maxe为0。对于新加的一条边,找到u->v目前的最大边与之比较,如果更小则切断原来的边连上新的边。u,v之间连边的时候以边界点为中间点。

    【代码】

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<iostream>
      4 #define FOR(a,b,c) for(int a=b;a<=c;a++)
      5 #define trav(u,i) for(int i=front[u];i;i=e[i].nxt)
      6 using namespace std;
      7 
      8 typedef long long ll;
      9 typedef unsigned int ul;
     10 const int N = 4e5+10;
     11 
     12 ll read() {
     13     char c=getchar();
     14     ll f=1,x=0;
     15     while(!isdigit(c)) {
     16         if(c=='-') f=-1; c=getchar();
     17     }
     18     while(isdigit(c))
     19         x=x*10+c-'0',c=getchar();
     20     return x*f;
     21 }
     22 
     23 struct Edge { int u,v,w;
     24 }e[N<<2];
     25 
     26 namespace LCT {
     27 
     28     struct Node {
     29         Node *ch[2],*fa;
     30         int rev,id,maxe;
     31         Node() ;
     32         void reverse() {
     33             rev^=1;
     34             swap(ch[0],ch[1]);
     35         }
     36         void up_push() {
     37             if(fa->ch[0]==this||fa->ch[1]==this) 
     38                 fa->up_push();
     39             if(rev) {
     40                 ch[0]->reverse();
     41                 ch[1]->reverse();
     42                 rev=0;
     43             }
     44         }
     45         void maintain() {
     46             int _max=-1;
     47             if(e[ch[0]->maxe].w>_max)
     48                 _max=e[ch[0]->maxe].w,maxe=ch[0]->maxe;
     49             if(e[ch[1]->maxe].w>_max)
     50                 _max=e[ch[1]->maxe].w,maxe=ch[1]->maxe;
     51             if(e[id].w>_max) maxe=id;
     52         }
     53     } *null=new Node,T[N],E[N<<2];
     54     Node::Node() {
     55         id=maxe=rev=0;
     56         fa=ch[0]=ch[1]=null;
     57     }
     58     
     59     void rot(Node* o,int d) {
     60         Node *p=o->fa;
     61         p->ch[d]=o->ch[d^1];
     62         o->ch[d^1]->fa=p;
     63         o->ch[d^1]=p;
     64         o->fa=p->fa;
     65         if(p==p->fa->ch[0])
     66             p->fa->ch[0]=o;
     67         else if(p==p->fa->ch[1])
     68             p->fa->ch[1]=o;
     69         p->fa=o;
     70         p->maintain();
     71     }
     72     void splay(Node *o) {
     73         o->up_push();
     74         Node *nf,*nff;
     75         while(o->fa->ch[0]==o||o->fa->ch[1]==o) {
     76             nf=o->fa,nff=nf->fa;
     77             if(o==nf->ch[0]) {
     78                 if(nf==nff->ch[0]) rot(nf,0);
     79                 rot(o,0);
     80             } else {
     81                 if(nf==nf->ch[1]) rot(nf,1);
     82                 rot(o,1);
     83             }
     84         }
     85         o->maintain();
     86     }
     87     void Access(Node* o) {
     88         Node *son=null;
     89         while(o!=null) {
     90             splay(o);
     91             o->ch[1]=son;
     92             o->maintain();
     93             son=o; o=o->fa;
     94         }
     95     }
     96     void evert(Node* o) {
     97         Access(o);
     98         splay(o);
     99         o->reverse();
    100     }
    101     void Link(Node* u,Node* v) {
    102         evert(u);
    103         u->fa=v;
    104     }
    105     void Cut(Node* u,Node* v) {
    106         evert(u);
    107         Access(v); splay(v);
    108         u->fa=v->ch[0]=null;
    109         v->maintain();
    110     }
    111     Node* find(Node* o) {
    112         while(o->fa!=null) o=o->fa;
    113         return o;
    114     }
    115     
    116 }
    117 using namespace LCT;
    118 
    119 const int inf = 1e9+10;
    120 
    121 int n,m,K;
    122 
    123 int query(Node *u,Node *v)
    124 {
    125     evert(u);
    126     Access(v),splay(v);
    127     return v->maxe;
    128 }
    129 void insert(Node *u,Node *v,int x)
    130 {
    131     if(e[x].u==e[x].v) return ;
    132     if(find(u)==find(v)) {
    133         int maxe=query(u,v);
    134         if(e[x].w>=e[maxe].w) return ;
    135         Cut(&E[maxe],&T[e[maxe].v]);
    136         Cut(&E[maxe],&T[e[maxe].u]);
    137     }
    138     Link(u,&E[x]);
    139     Link(v,&E[x]);
    140 }
    141 
    142 int main()
    143 {
    144     n=read(),m=read(),K=read();
    145     FOR(i,1,m) E[i].id=E[i].maxe=i;
    146     FOR(i,1,m) {
    147         e[i].u=read(),e[i].v=read(),e[i].w=read();
    148         insert(&T[e[i].u],&T[e[i].v],i);
    149     }
    150     FOR(i,1,K) {
    151         int u=read(),v=read();
    152         printf("%d
    ",e[query(&T[u],&T[v])].w);
    153     }
    154     return 0;
    155 }
    View Code
  • 相关阅读:
    虚拟机中Linux 下安装tools
    各个复位标志解析,让我们对MCU的程序的健康更有把控
    用过的两种鼠标右键添加快捷指令方法
    一个ftp协议传输文件之后执行脚本无法工作的情况
    一文入门Linux下gdb调试(二)
    一文入门Linux下gdb调试(一)
    VS CODE远程办公篇一
    Kwp2000协议的应用(程序后续篇)
    Kwp2000协议的应用(程序原理篇)
    Kwp2000协议的应用(硬件原理使用篇)
  • 原文地址:https://www.cnblogs.com/lidaxin/p/5321916.html
Copyright © 2011-2022 走看看