【NOIP2017提高A组模拟8.16】最短路
来源:互联网 发布:武汉网站seo顾问 编辑:程序博客网 时间:2024/06/05 08:11
分析
直接spfa只能拿60分,
对于没有环的情况,就是一棵树,
那就在树上跑倍增。
对于有环的情况,我们就想将它变为树。
对于一个环,选一个点作为环顶,
环上的其他点就向环顶连一条边,边权为这个点到环顶的最短路。
对于一个询问,我们用倍增将它们弄得同一个环上面,
然后就计算环上的最短距离。
对于找环,运用tarjan的思想。
code
#include<queue>#include<cstdio>#include<iostream>#include<algorithm>#include <cstring>#include <string.h>#include <cmath>#include <math.h>#define ll long long#define N 103000#define db double#define P putchar#define G getchar#define mo 1000000007using namespace std;char ch;void read(int &n){ n=0; ch=G(); while((ch<'0' || ch>'9') && ch!='-')ch=G(); ll w=1; if(ch=='-')w=-1,ch=G(); while('0'<=ch && ch<='9')n=n*10+ch-'0',ch=G(); n*=w;}void write(int x){ if(x>9) write(x/10); P(x%10+'0');}int next[N*2],a[N*2],v[N*2],last[N],tot,fa[N];int next1[N*2],a1[N*2],v1[N*2],last1[N],tot1;int n,m,q,x,y,z,cnt,top;int dfn[N],id,belong[N],f1[N],f2[N],htop[N];bool bz[N];int deep[N],f[N][14],g[N][14];struct node{ int x,s;}st[N];void ins(int x,int y,int z){ next[++tot]=last[x]; a[tot]=y; v[tot]=z; last[x]=tot;}void ins1(int x,int y,int z){ next1[++tot1]=last1[x]; a1[tot1]=y; v1[tot1]=z; last1[x]=tot1;}void link(int x){ bz[x]=1; for(int i=last[x];i;i=next[i]) { int y=a[i]; if(y!=fa[x] && !bz[y]) { if((belong[x]!=belong[y] || !belong[x] && !belong[y]) && htop[y]!=x && htop[x]!=y) { ins1(x,y,v[i]); ins1(y,x,v[i]); } link(y); } }}void dfs(int x){ dfn[x]=++id; for(int i=last[x];i;i=next[i]) { int y=a[i]; if(y!=fa[x] && !dfn[y]) { fa[y]=x; top++; st[top].x=y; st[top].s=v[i]; dfs(y); } else if(y!=fa[x] && dfn[y]<dfn[x]) { cnt++; int p=top,sum=v[i]; while(st[p].x!=y && p) { f1[st[p].x]=sum;//顺时针 sum+=st[p].s; p--; } sum=st[p+1].s; for(int i=p+1;i<=top;i++) { htop[st[i].x]=y;//环顶 belong[st[i].x]=cnt;//染色 f2[st[i].x]=sum;//逆时针 int mi=min(f1[st[i].x],f2[st[i].x]); ins1(st[i].x,y,mi); ins1(y,st[i].x,mi); sum+=st[i+1].s; } } } top--;}void build(int x){ for(int i=last1[x];i;i=next1[i]) { int y=a1[i]; if(y!=f[x][0]) { f[y][0]=x; g[y][0]=v1[i]; deep[y]=deep[x]+1; build(y); } }}int lca(int x,int y){ int s=0; if(deep[y]>deep[x])swap(x,y); for(int i=13;i>=0;i--) if(deep[f[x][i]]>=deep[y])s+=g[x][i],x=f[x][i]; if(x==y)return s; for(int i=13;i>=0;i--) if(f[x][i]!=f[y][i])s+=g[x][i]+g[y][i],x=f[x][i],y=f[y][i]; if(x!=y && belong[x] && belong[x]==belong[y]) s+=min(min(f1[x]+f2[y],f1[y]+f2[x]),min(abs(f2[x]-f2[y]),abs(f1[x]-f1[y])));else s+=g[x][0]+g[y][0]; return s;}int main(){ read(n);read(m);read(q); for(int i=1;i<=m;i++) read(x),read(y),read(z),ins(x,y,z),ins(y,x,z); dfs(1); link(1); build(1); for(int j=1;j<14;j++) for(int i=1;i<=n;i++) f[i][j]=f[f[i][j-1]][j-1],g[i][j]=g[i][j-1]+g[f[i][j-1]][j-1]; for(int i=1;i<=q;i++) { read(x);read(y); write(lca(x,y)); P('\n'); }}
阅读全文
0 0
- 【NOIP2017提高A组模拟8.16】最短路
- 【JZOJ5287】【NOIP2017提高A组模拟8.16】最短路
- 【JZOJ5287】【NOIP2017提高组模拟】最短路
- 【NOIP2017提高A组模拟8.16】花花的森林
- A【NOIP2017提高组模拟12.18】
- 【JZOJ4928】【NOIP2017提高组模拟12.18】A
- 【NOIP2017提高组模拟12.18】A
- 【JZOJ4928】【NOIP2017提高组模拟12.18】A
- 【NOIP2017提高A组模拟7.7】图
- 【NOIP2017提高A组模拟7.13】abcd
- 区间【NOIP2017提高A组模拟7.10】
- 【NOIP2017提高A组模拟8.22】密码
- 【NOIP2017提高A组模拟8.23】密码
- 【NOIP2017提高A组模拟8.24】早苗
- 【NOIP2017提高A组模拟8.24】提米树
- 空【NOIP2017提高A组模拟8.24】
- 【NOIP2017提高A组模拟8.25】影子
- 区间【NOIP2017提高A组模拟9.16】
- javaScript之Math和Date对象
- 数据库的常见查询操作
- pip install superset 出现 No package 'libffi' found 错误
- Largest Rectangle in Histogram&&Maximal Rectangle
- RecyclerView实现上拉加载更多
- 【NOIP2017提高A组模拟8.16】最短路
- Quartz定时调度器05
- spring扩展schema文件
- Copy List with Random Pointer leetcode java
- python如何使用unit test 模块
- 一位资深程序员大牛给予Java初学者的学习路线建议
- C语言及程序设计初步 Lesson 6 项目:计算串联电阻值
- 模式总结(进行中)
- 【JZOJ 5284】 超级翻转