【NOIP2013提高组 day1】货车运输
2019-07-17 22:55
85 查看
版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/Flag_z/article/details/96378498
分析
先求最大生成树,把一些多余的边去掉
求最近公共祖先LCA 可用树上倍增的方法 (Tarjan好像也行不知道会不会超时
询问前处理
w[i][j]=min(w[f[i][j-1]][j-1],w[i][j-1])
最后对于询问的x,y返回ans
ans=min(ans,w[i][j]) (w[i][j]在x,y到lca(x,y)路径上)
可能有一点点玄学,具体看代码就清楚 更玄学 啦~
代码如下
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int N=10005,inf=0x3f3f3f3f; struct E{ int x,y,val; }edge[50005]; struct tree{ int ver,to,w; }edge2[100050]; int n,m,tot=0,p,head[N],t; int fa[N],f[N][21],w[N][21],d[N]; int read(){ int sum=0,f=1; char ch=getchar(); while(ch>'9'||ch<'0'){ if(ch=='-')f=-1; ch=getchar(); } while(ch>='0'&&ch<='9'){ sum=(sum<<3)+(sum<<1)+ch-'0'; ch=getchar(); } return sum*f; } bool comp(E a,E b){ return a.val>b.val; } int find(int x){ if(x==fa[x])return x; return fa[x]=find(fa[x]); } void add(int x,int y,int z){ edge2[++tot].ver=y; edge2[tot].to=head[x]; edge2[tot].w =z; head[x]=tot; } void kruskal(){ for(int i=1;i<=n;i++) fa[i]=i; for(int i=1;i<=m;i++) { int x=find(edge[i].x); int y=find(edge[i].y); if(x==y)continue; fa[x]=y; add(edge[i].x,edge[i].y,edge[i].val); add(edge[i].y,edge[i].x,edge[i].val); } } void dfs(int x) { for(int i=head[x];i;i=edge2[i].to) { int y=edge2[i].ver; if(d[y])continue; d[y]=d[x]+1; f[y][0]=x; w[y][0]=edge2[i].w; dfs(y); } } int lca(int x,int y){ int ans=inf; if(find(x)!=find(y))return -1; if(d[x]>d[y])swap(x,y); for(int i=t;i>=0;i--) if(d[f[y][i]]>=d[x]){ ans=min(ans,w[y][i]); y=f[y][i]; } if(x==y)return ans; for(int i=t;i>=0;i--){ if(f[x][i]!=f[y][i]){ ans=min(ans,w[x][i]); ans=min(ans,w[y][i]); x=f[x][i];y=f[y][i]; } } ans=min(ans,min(w[x][0],w[y][0])); return ans; } void init(){ for(int i=1;i<=n;i++) { if(!d[i]){ d[i]=1; f[i][0]=i; w[i][0]=inf; dfs(i); } } for(int i=1;i<=t;i++) for(int j=1;j<=n;j++) { f[j][i]=f[f[j][i-1]][i-1]; w[j][i]=min(w[f[j][i-1]][i-1],w[j][i-1]); } } int main(){ // freopen("truck.in","r",stdin); // freopen("truck.out","w",stdout); n=read(); m=read(); int x,y,z; t=(int)(log(n)/log(2))+1; for(int i=1;i<=m;i++) { edge[i].x=read(); edge[i].y=read(); edge[i].val=read(); } sort(edge+1,edge+m+1,comp); kruskal(); init(); p=read(); for(int i=1;i<=p;i++) { x=read(); y=read(); cout<<lca(x,y)<<endl; } return 0; }
相关文章推荐
- JZOJsenior3534、luoguP1967.【NOIP2013提高组day1】货车运输
- NOIP2013复赛提高组day1(A:转圈游戏 B:火柴排队 C:货车运输)
- Noip 提高组 2013 Day1 T3 货车运输 Kruskal+倍增
- 【NOIP】提高组2013 货车运输
- NOIP 2013 提高组 货车运输
- 【noip2013提高组day1T3】 货车运输 RMQ+LCA+倍增+最大生成树
- [NOIP2013] 提高组 洛谷P1967 货车运输
- NOIP2013提高组 货车运输
- 【NOIP2013提高组T3】货车运输-最大生成树+倍增LCA
- Noip2013 Day1 T3 货车运输(树上倍增)
- NOIP2013 Day1 T3 货车运输
- 洛谷P1967 [NOIP2013提高组Day1T2]货车运输
- NOIP提高组 2013货车运输
- NOIP提高组 2013货车运输
- Code[vs]3287【NOIP2013提高组】【7.13考试第四题】货车运输
- NOIP2013 Day1 T3 货车运输
- 【NOIP 2013 Day1 T3】货车运输(最大生成树+LCA)
- NOIP 2013 Day1 T3 货车运输
- noip2013 day1-3 货车运输
- NOIP提高组2013-货车运输