山东济南彤昌机械科技有限公司 山东济南江鹏工贸游有限公司

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\n",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\n",e[query(&T[u],&T[v])].w);
153     }
154     return 0;
155 }
View Code

 

posted on 2016-03-26 08:37  hahalidaxin  阅读(412)  评论(0编辑  收藏  举报