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 }
【思路二】
用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 }
posted on 2016-03-26 08:37 hahalidaxin 阅读(412) 评论(0) 编辑 收藏 举报