最大生成树+链剖——Luogu1967 [NOIP2013]货车运输
来源:互联网 发布:零售软件是什么 编辑:程序博客网 时间:2024/04/30 15:06
题面:Luogu1967
乍一看,网络流水题?
不存在的,有多组询问+起始点和终止点各不相同。。。
那不能用网络流还能用什么?
我们可以发现,题目所要求的那条路径一定在当前连通块的最大生成树上
这是一定的,否则找不到更大的一条路径里边的最小值比这条更大
所以就很容易想到Kruskal求出最大生成森林(图不一定连通)之后在树上进行操作了
具体什么操作呢?就是找两点间在树上路径的最小值即可
如果两点属于不同生成树,输出-1
看其他网上题解都是啥倍增一下或者找LCA之类的东西
我呢直接大力树剖,当然啦调了半个小时QAQ
#include<cstdio>#include<algorithm>#include<cmath>#include<cstring>#include<iostream>#include<cstdlib>#include<queue>#include<string>#include<ctime>#include<map>#include<climits>#include<set>using namespace std;struct ppap{int x,y,v;}a[100001];inline bool cmp(ppap a,ppap b){return a.v>b.v;}int nedge=0,p[200001],c[200001],nex[200001],head[200001];int n,m,gfa[100001],fa[100001],deep[100001],s[100001],son[100001],top[100001],jzq[400001];int sum=0,xs[400001],sx[400001],lt[400001],rt[400001],t[400001];inline void addedge(int x,int y,int z){ p[++nedge]=y;c[nedge]=z;nex[nedge]=head[x];head[x]=nedge;}inline int getfather(int v){return gfa[v]==v?v:gfa[v]=getfather(gfa[v]);}inline void dfs(int x,int Fa,int dep){ fa[x]=Fa;deep[x]=dep;s[x]=1; for(int k=head[x];k;k=nex[k])if(p[k]!=Fa){ dfs(p[k],x,dep+1);s[x]+=s[p[k]]; if(!son[x]||s[p[k]]>s[son[x]])son[x]=p[k]; }}inline void dfss(int x,int g,int qz){ top[x]=g;sx[x]=++sum;xs[sum]=x;jzq[x]=qz; if(!son[x])return; for(int k=head[x];k;k=nex[k])if(p[k]==son[x]){dfss(son[x],g,c[k]);break;} for(int k=head[x];k;k=nex[k])if(p[k]!=fa[x]&&p[k]!=son[x])dfss(p[k],p[k],c[k]);}inline void build(int l,int r,int nod){ lt[nod]=l;rt[nod]=r; if(l==r){t[nod]=jzq[xs[l]];return;} int mid=l+r>>1; build(l,mid,nod*2);build(mid+1,r,nod*2+1); t[nod]=min(t[nod*2],t[nod*2+1]);}inline int ssum(int i,int j,int nod){ if(lt[nod]>=i&&rt[nod]<=j)return t[nod]; int mid=lt[nod]+rt[nod]>>1,ans=1e9; if(i<=mid)ans=min(ans,ssum(i,j,nod*2)); if(j>mid)ans=min(ans,ssum(i,j,nod*2+1)); return ans;}inline int fsum(int x,int y){ int fx=top[x],fy=top[y],ans=1e9; while(fx!=fy){ if(deep[fx]<deep[fy])swap(fx,fy),swap(x,y); ans=min(ans,ssum(sx[fx],sx[x],1)); x=fa[fx];fx=top[x]; } if(deep[x]>deep[y])swap(x,y); ans=min(ans,ssum(sx[x]+1,sx[y],1)); return ans;}int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=m;i++)scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].v); sort(a+1,a+m+1,cmp); for(int i=1;i<=n;i++)gfa[i]=i; int cnt=0; for(int i=1;i<=m;i++){ int fx=getfather(a[i].x),fy=getfather(a[i].y); if(fx==fy)continue;cnt++; gfa[fx]=fy;addedge(a[i].x,a[i].y,a[i].v);addedge(a[i].y,a[i].x,a[i].v); if(cnt==n-1)break; }//以上Kruskal求最大生成树 for(int i=1;i<=n;i++)if(!deep[i])dfs(i,0,1),dfss(i,0,0);//从这里开始树剖 build(1,n,1); scanf("%d",&m); for(int i=1;i<=m;i++){ int x,y;scanf("%d%d",&x,&y); int fx=getfather(x),fy=getfather(y); if(fx!=fy)puts("-1");//判连通 else printf("%d\n",fsum(x,y)); } return 0;}
阅读全文
1 0
- 最大生成树+链剖——Luogu1967 [NOIP2013]货车运输
- NOIP2013货车运输(最大生成树+LCA)
- NOIP2013 货车运输(最大生成树+LCA)
- [NOIP2013]货车运输,最大生成树+LCA
- [NOIP2013] 货车运输 最大生成树 LCA
- NOIP2013货车运输 最大生成树+lca
- NOIP2013货车运输 (最大生成树,分块求LCA)
- 【树链剖分】【最大生成树】[NOIP2013]codevs3287 货车运输
- NOIP2013 货车运输 (最大生成树+树上倍增LCA)
- noip2013货车运输 最大生成树+LCA 【pascal】
- [noip2013] 货车运输(最大生成树+并查集+LCA)
- 洛谷 1967 [NOIP2013] 货车运输 最大生成树+倍增
- Luogu1967 [NOIP2013] 货车运输 解题报告【Kruskal】【LCA】【倍增】
- luogu1967 货车运输
- luogu1967 货车运输
- [最大生成树+LCA]NOIP 2013——货车运输
- 【题】【树(最大生成树&LCA)】NKOJ 2495 货车运输 【NOIP2013-D1T3】
- [NOIP2013]货车运输 D1 T3 kruscal最大生成树+树上倍增lca+rmq
- Android应用开发之所有动画使用详解
- H
- 20170602心情总结
- 文本分类特征选择方法
- 第十五周
- 最大生成树+链剖——Luogu1967 [NOIP2013]货车运输
- 生产者与消费者模型
- 使用Eclipse Babel语言包汉化eclipse
- 操作系统(Operating System)16 分布式处理,客户-服务器和集群
- css默认样式
- leetcode 515. Find Largest Value in Each Tree Row
- 支持向量机(SVM)常考点
- JSP用到一个下拉框<select> 页面刷新后,保持选中的值
- HTML5的input