【NOIP2013模拟】Freda的传呼机
来源:互联网 发布:广告宣传单设计软件 编辑:程序博客网 时间:2024/05/16 09:24
Description
给出一张n个点,m条边的无向联通图,和q次询问,每次询问x到y的最短路。
n,q<=10^4,m<=1.2*10^4
时限100ms
10% n<=10^3,m<=1.2*10^3
另外30% n=m+1
另外50% n=m
Solution
这题画风突然就变了。
10%暴力,30%树,50%换套树,10%。。。仙人掌!@#¥%……&*
还开100ms,吓得我都不敢打玄学算法sp(b)fa了.
不过事实证明出题人不卡。。。
首先我们从root开始跑一遍sp(b)fa
然后把仙人掌变成树
链接一个把仙人掌变成树的方法
这样我们就得到了一颗仙人掌树(是这样叫的吧?)
并且这棵树中的所有环顶(父亲)都是儿子的spfa必经点。
那么对于两个点x,y,我们我们把他们往上跳,跳到lca的下面,设为a和b。
如果这两个点不属于一个一个环,那么答案就是dis[x]+dis[y]-2*dis[lca]
如果属于,那么我们就用dis[x]-dis[a]+dis[y]-dis[b]再加上a到b走环的距离(min一下就好了) infleaking同学竟然比我早A,不爽(*  ̄︿ ̄)
Code
#include<cmath>#include<cstdio>#include<cstring>#include<algorithm>#define fo(i,a,b) for(int i=a;i<=b;i++)#define fd(i,a,b) for(int i=a;i>=b;i--)#define rep(i,a) for(int i=last[a];i;i=next[i])#define N 22005using namespace std;int n,m,x,y,z,l,q,tot;int d[N],c[N],dfn[N],dis[N],cir[N],p[N],len[N];int t[N*2],v[N*2],next[N*2],last[N],fa[N][17],que[N*5];bool e[N*2],bz[N];void add(int x,int y,int z) { t[++l]=y;v[l]=z;next[l]=last[x];last[x]=l;}void spfa() { memset(dis,127,sizeof(dis));dis[1]=0; int i=0,j=1;bz[1]=1;que[1]=1; while (i<j) { rep(k,que[++i]) if (dis[t[k]]>dis[que[i]]+v[k]) { dis[t[k]]=dis[que[i]]+v[k]; if (!bz[t[k]]) bz[t[k]]=1,que[++j]=t[k]; } bz[que[i]]=0; }}void cate(int S,int T,int line) { e[line]=e[line^1]=1;c[++c[0]]=v[line]; for(int i=T;i!=S;i=t[p[i]^1]) { cir[i]=c[0];e[p[i]]=e[p[i]^1]=1; c[c[0]]+=v[p[i]];add(S,i,0);add(i,S,0); }}void dfs(int x) { dfn[x]=++tot; rep(i,x) if (i<=2*m+1&&i!=(p[x]^1)) if (!dfn[t[i]]) { p[t[i]]=i;len[t[i]]=len[x]+v[i]; dfs(t[i]); } else if (dfn[t[i]]<dfn[x]) cate(t[i],x,i);}void make(int x,int y) { d[x]=d[y]+1;fa[x][0]=y; rep(i,x) if (t[i]!=y&&!e[i]) make(t[i],x);} int lca(int &x,int &y) { if (d[x]<d[y]) swap(x,y); fd(j,16,0) if (d[fa[x][j]]>=d[y]) x=fa[x][j]; if (x==y) return x; fd(j,16,0) if (fa[x][j]!=fa[y][j]) x=fa[x][j],y=fa[y][j]; return fa[x][0];} int main() { scanf("%d%d%d",&n,&m,&q);l=1; fo(i,1,m) scanf("%d%d%d",&x,&y,&z),add(x,y,z),add(y,x,z); spfa();dfs(1);make(1,0); fo(j,1,16) fo(i,1,n) fa[i][j]=fa[fa[i][j-1]][j-1]; for(;q;q--) { scanf("%d%d",&x,&y);int a=x,b=y;z=lca(x,y); if (cir[x]&&cir[y]&&cir[x]==cir[y]) { z=abs(len[x]-len[y]); printf("%d\n",dis[a]-dis[x]+dis[b]-dis[y]+min(z,c[cir[x]]-z)); continue; } printf("%d\n",dis[a]+dis[b]-2*dis[z]); }}
0 0
- 【NOIP2013模拟】Freda的传呼机
- 【NOIP2013模拟】Freda的传呼机
- JZOJ3395. 【NOIP2013模拟】Freda的传呼机
- 【NOIP2013模拟】Freda的传呼机 题解+代码
- [JZOJ3395]【NOIP2013模拟】Freda的传呼机
- jzoj3395 Freda的传呼机
- Freda的传呼机
- [bzoj3047] Freda的传呼机
- [JZOJ 3395] Freda的传呼机
- 【BZOJ3047&2125】Freda的传呼机
- bzoj3047: Freda的传呼机&bzoj2125: 最短路
- Freda的传呼机 倍增LCA+dfs判环
- BZOJ 2125 最短路 && BZOJ 3047 Freda的传呼机【仙人掌最短路
- 【NOIP2013模拟】KC的陶器
- 【NOIP2013模拟】Rainbow的信号
- 【NOIP2013模拟】Rainbow的信号
- 传呼机
- wiki Freda的道路
- how to install window exe program on ubuntu
- Git Base 操作
- android自定义控件系列
- SHOPNC 插件机制的实现记录
- epoll的LT、ET模式和EPOLLONESHOT事件实例介绍
- 【NOIP2013模拟】Freda的传呼机
- UI控件大全
- 2.6 MYSQL的输出格式
- LeetCode题解——House Robber III
- codeforces58
- I/O复用之 select和epoll
- 欢迎使用CSDN-markdown编辑器
- iOS开发之高级视图—— UITableView操作——新增
- 软件下载地址