uva 12655 (树链剖分+生成树 好题)
来源:互联网 发布:仿淘宝商城系统 编辑:程序博客网 时间:2024/05/20 05:29
题意:
给出一张图,s次询问求两点间所有路径中最大的最小值
分析:
首先看到的是一张图,看上去貌似和树无关,仔细想想求两点间路径的最小值如何求,和什么有关,首先想到能不能离线处理,这样一想之后发现其实如果我们让大边先去建图,一直到建成一棵生成树,那么是不是两点间的答案就唯一确定了,很明显是的,因为此时小边已经排除在外了,那么如果有相同权值边会不会影响结果,很明显也不会,因为我们是按照从大到小建树的,后面的边会影响前面的边,而前面的边不会影响结果,树建成之后剩下的就是树链剖分的活了。
#include<cstring>#include<string>#include<iostream>#include<queue>#include<cstdio>#include<algorithm>#include<map>#include<cstdlib>#include<cmath>#include<vector>//#pragma comment(linker, "/STACK:1024000000,1024000000");using namespace std;#define INF 0x3f3f3f3f#define maxn 200005int e[maxn];int x[maxn],y[maxn],c[maxn],cost[maxn],val1[maxn],val2[maxn];int fir[maxn],nex[maxn],v[maxn],e_max;int son[maxn],fa[maxn],deep[maxn],siz[maxn],top[maxn],pos[maxn],tot;int s[maxn],mi[4*maxn];void init_(int n){ for(int i=1;i<=n;i++) s[i]=i; memset(son,-1,sizeof son); memset(fir,-1,sizeof fir); e_max=0; tot=0;}void add_edge(int s,int t,int c){ int e=e_max++; cost[e]=c; v[e]=t; nex[e]=fir[s]; fir[s]=e;}int root(int x){ return x==s[x]?x:s[x]=root(s[x]);}bool cmp(int a,int b){ return c[a]>c[b];}void dfs1(int k,int pre,int d){ deep[k]=d; siz[k]=1; fa[k]=pre; for(int i=fir[k];~i;i=nex[i]) { int e=v[i]; if(e!=pre) { val1[e]=cost[i]; dfs1(e,k,d+1); siz[k]+=siz[e]; if(son[k]==-1||siz[son[k]]<siz[e]) son[k]=e; } }}void dfs2(int k,int sp){ top[k]=sp; pos[k]=tot++; val2[pos[k]]=val1[k]; if(son[k]==-1) return ; dfs2(son[k],sp); for(int i=fir[k];~i;i=nex[i]) { int e=v[i]; if(e!=fa[k]&&e!=son[k]) { dfs2(e,e); } }}void init(int l,int r,int k){ if(l==r) { mi[k]=val2[l]; return ; } int mid=l+r>>1; init(l,mid,k<<1); init(mid+1,r,k<<1|1); mi[k]=min(mi[k<<1],mi[k<<1|1]);}int query(int s,int t,int l,int r,int k){ if(s==l&&r==t) { return mi[k]; } int mid=l+r>>1; if(t<=mid) return query(s,t,l,mid,k<<1); else if(s>mid) return query(s,t,mid+1,r,k<<1|1); else return min(query(s,mid,l,mid,k<<1),query(mid+1,t,mid+1,r,k<<1|1));}int Query(int s,int t){ int ans=INF; int f1=top[s],f2=top[t]; while(f1!=f2) { if(deep[f1]<deep[f2]) swap(f1,f2),swap(s,t); ans=min(ans,query(pos[f1],pos[s],1,tot-1,1)); s=fa[f1]; f1=top[s]; } if(s==t) return ans; if(deep[s]>deep[t]) swap(s,t); ans=min(ans,query(pos[s]+1,pos[t],1,tot-1,1)); return ans;}int main(){ int n,m,q; while(scanf("%d%d%d",&n,&m,&q)!=EOF) { init_(n); for(int i=0;i<m;i++) { scanf("%d%d%d",&x[i],&y[i],&c[i]); e[i]=i; } sort(e,e+m,cmp); for(int i=0;i<m;i++) { int p=e[i]; int _x=root(x[p]),_y=root(y[p]); if(_x!=_y) { s[_x]=_y; add_edge(x[p],y[p],c[p]); add_edge(y[p],x[p],c[p]); } } dfs1(1,-1,1); dfs2(1,1); init(1,tot-1,1); while(q--) { int a,b; scanf("%d%d",&a,&b); int ans=Query(a,b); printf("%d\n",ans); } } return 0;}
0 0
- uva 12655 (树链剖分+生成树 好题)
- 最小生成树的思维好题
- UVA 11354 - Bond (最小生成树 + 树链剖分)
- uva 10125 - Sumsets好题
- UVa 11235 RMQ好题
- UVa 11732 trie好题
- UVA 1395 生成树
- UVA 1151 生成树
- UVA-12166-Equilibrium Mobile【思维】【二叉树】【好题】
- UVA 10369 最小生成树
- uva 10397(最小生成树)
- uva 10034(最小生成树)
- uva 10369(最小生成树)
- uva 10766 生成树计数
- UVa 1395 最小生成树
- uva 1151最小生成树
- uva 10369 最小生成树
- UVa 11572 - Unique Snowflakes (好题)
- c++primer读书笔记:2.4 const 限定符
- 重定向可以在头部指定
- 滴滴实习生面试
- 十、NOSQL与缓存系统-Redis安装
- 自增自减运算符的stdcall现象
- uva 12655 (树链剖分+生成树 好题)
- mDNS原理的简单理解
- fragment_onresum
- 解决UC浏览器、微信浏览器使用display:flex;的兼容性问题
- jQuery 源码解析笔记(一)
- java带包类程序的编译和执行
- 读快枪手游戏源代码所获
- HDU 4586 Play the dice (数学期望)
- 155. Min Stack [easy] (Python)