【JZOJ5287】【NOIP2017提高组模拟】最短路
来源:互联网 发布:医院网络建设的新闻 编辑:程序博客网 时间:2024/06/05 07:28
Description
Solution
这题就是要求一个仙人掌图上面的两点间最短路径。
那么我们一开始可以从1号节点开始跑一次spfa,然后加入两个点的在dfs树上的lca不是环上的点的话,那么直接用d[x]+d[y]-2*d[lca]就可以了。
但是如果是环上的点要怎么办?
我们环上的点可以有两条路径相互到达,那么我们可以把两个点同时跳到同一个环上然后在计算环上的距离。那么我们可以把环上的点的深度都拆成相同的,然后对于不同的环还要打上不同的标记,然后每个环上的点都要向环顶连一条边,最后构出一张新图。
构出之后再更新倍增数组,然后就按照上面的做就可以了。
环上的路径可以用从根到当前点的前缀和统计。
Code
#include<iostream>#include<stdio.h>#include<string.h>#include<algorithm>#include<math.h>#define fo(i,a,b) for(i=a;i<=b;i++)#define fod(i,a,b) for(i=a;i>=b;i--)#define rep(i,a) for(i=first[a];i;i=next[i])using namespace std;const int maxn=2e5+7;int i,j,k,l,t,n,m,ans,q;int first[maxn*2],last[maxn*2],next[maxn*2],num,chang[maxn*2],o;int first1[maxn*2],last1[maxn*2],next1[maxn*2],num1;int dfn[maxn],d[maxn],data[maxn],dfx,c[maxn],h[maxn],f[maxn][21],g[maxn],tot,dis[maxn];int b[maxn],fa[maxn],yi,er,deep[maxn],p[maxn];bool bz[maxn],az,cz[maxn*2];void add(int x,int y,int z){ last[++num]=y,next[num]=first[x],first[x]=num,chang[num]=z;}void spfa(){ memset(d,127,sizeof(d)); int head=0,tail=1,now,i; bz[1]=1;d[1]=0;data[1]=1; while(head<tail){ now=data[++head]; rep(i,now){ if(d[now]+chang[i]>=d[last[i]])continue; d[last[i]]=d[now]+chang[i]; if(!bz[last[i]])bz[last[i]]=1,data[++tail]=last[i]; } bz[now]=0; }}void dfs1(int x,int y,int z){ h[++tot]=chang[z];c[x]=tot;h[tot]+=chang[p[x]];add(y,x,0),add(x,y,0);c[y]=tot; cz[p[x]]=cz[p[x]^1]=1; while(fa[x]!=y){ x=fa[x];add(y,x,0),add(x,y,0); cz[p[x]]=cz[p[x]^1]=1; h[tot]+=chang[p[x]]; c[x]=tot; }}void dfs(int x,int y){ int i;dfn[x]=++dfx; rep(i,x){ if((p[x]^1)==i||i>2*m+1)continue; if(dfn[last[i]]&&dfn[last[i]]<dfn[x]){ cz[i]=cz[i^1]=1; dfs1(x,last[i],i); continue; } else if(!dfn[last[i]]){ g[last[i]]=g[x]+chang[i];p[last[i]]=i;fa[last[i]]=x; dfs(last[i],x); } }}void dfs2(int x,int y){ int i;f[x][0]=y;deep[x]=deep[y]+1; rep(i,x)if(last[i]!=y&&!cz[i]&&!cz[i^1])dfs2(last[i],x);}int lca(int &x,int &y){ int i;if(deep[x]<deep[y])swap(x,y); fod(i,20,0)if(deep[f[x][i]]>deep[y])x=f[x][i]; if(deep[x]!=deep[y])x=f[x][0]; fod(i,20,0)if(f[x][i]!=f[y][i])x=f[x][i],y=f[y][i]; if(x!=y)return f[x][0];return x;}int main(){// freopen("fan.in","r",stdin);// freopen("fan.out","w",stdout); scanf("%d%d%d",&n,&m,&q);num=1; fo(i,1,m)scanf("%d%d%d",&k,&l,&t),add(k,l,t),add(l,k,t); spfa(); dfs(1,0); dfs2(1,0); fo(j,1,20)fo(i,1,n)f[i][j]=f[f[i][j-1]][j-1]; while(q--){ scanf("%d%d",&k,&l);yi=k,er=l; o=lca(k,l); if(q==9924){ ans=ans; } if(c[l]&&c[k]==c[l]&&c[k]){ ans=d[yi]+d[er]-d[k]-d[l]+min(abs(g[k]-g[l]),h[c[k]]-abs(g[k]-g[l])); printf("%d\n",d[yi]+d[er]-d[k]-d[l]+min(abs(g[k]-g[l]),h[c[k]]-abs(g[k]-g[l]))); } else printf("%d\n",d[yi]+d[er]-2*d[o]); ans=d[yi]+d[er]-2*d[o]; if(ans==246523){ ans=ans; } }}
阅读全文
1 0
- 【JZOJ5287】【NOIP2017提高组模拟】最短路
- 【JZOJ5287】【NOIP2017提高A组模拟8.16】最短路
- 【NOIP2017提高A组模拟8.16】最短路
- 【JZOJ5287】最短路
- NOIP2017 7.17模拟 Minimum (最短路+最小生成树)
- 4920. 【NOIP2017提高组模拟12.10】降雷皇
- 【NOIP2017提高组模拟12.10】神炎皇
- 【NOIP2017提高组模拟12.10】神炎皇
- 【NOIP2017提高组模拟12.10】幻魔皇
- JZOJ4919. 【NOIP2017提高组模拟12.10】神炎皇
- 【NOIP2017提高组模拟12.10】神炎皇
- 【NOIP2017提高组模拟12.10】幻魔皇
- 【NOIP2017提高组模拟12.10】幻魔皇
- 【JZOJ4921】【NOIP2017提高组模拟12.10】幻魔皇
- 【JZOJ4920】【NOIP2017提高组模拟12.10】降雷皇
- 【JZOJ4919】【NOIP2017提高组模拟12.10】神炎皇
- 神炎皇【NOIP2017提高组模拟12.10】
- 【NOIP2017提高组模拟12.10】幻魔皇
- Oracle学习笔记 -- day04 单行函数字符、单行函数转换、多行函数
- 线段树板子
- Mysql插入语句value与values的区别
- shell中各种括号()、(())、[]、[[]]、{}的作用及使用场景
- 超分辨率重建之VDSR
- 【JZOJ5287】【NOIP2017提高组模拟】最短路
- 拖拽移动RecyclerView
- 《史蒂夫·乔布斯传》感悟
- jms学习-基本概念(一)
- TensorFlow 测试 IRIS 数据
- 最全oracle单行函数之转换函数用法详解
- Gradle,Groovy与Android Studio中的Gradle详解
- JAVA8 十大新特性详解
- 陀螺仪数据处理