[JZOJ 3395] Freda的传呼机
来源:互联网 发布:数据库事务特性 老婆 编辑:程序博客网 时间:2024/06/05 20:08
Description
给定一个有
对于100%的数据,
时间限制
啊,我不会做!
嗯,当然,还有一点忘说了,只有三类数据:
- M=N-1(树)30%
- M=N(环套外向树)50%
- 每条边仅在一个简单环中(仙人掌)10%
什么,你问30%+50%+10%=90%!=100%,其实剩下那10%是送的。
Analysis
这是本蒟蒻的第一道仙人掌。
显然,仙人掌就包括了前两种情况,但是出题人毒瘤,不仅出这种业界毒瘤,仙人掌还只给10分。
这里有一种把仙人掌变成树的方法,感谢alan大神百度搜索提供的资料,搜索技术高超。像我这种蒟蒻搜到的全都是
真是美丽的仙人掌啊!
好吧,废话不说了。
上面的方法形象地解释就是这样:
定义环顶为一个环里dfn最小的点。
如图,设红色的点是环顶。
若两个点在同一个环中,如下图两个蓝色的点
那他们的距离显然是从环的两边走的较小的那一个。
所以我们要求出每个环的大小
当然,我们变成树之后,设询问的两个点为
若
否则,x,y不在同一个环中,所以直接用dis[x]-dis[u]+dis[y]-dis[v]+(u到v环上的距离)即可。
Code
#include<cstdio>#include<cmath>#include<cstring>#include<queue>#include<algorithm>#define fo(i,a,b) for(int i=a;i<=b;i++)#define fd(i,b,a) for(int i=b;i>=a;i--)#define efo(i,v) for(int i=last[v];i;i=next[i])using namespace std;const int N=10010,M=N*5;int tot,n,m,num,st[M],to[M],next[M],wei[M],last[N];int now,dep[N],dis[N],di[N],from[N],dfn[N],val[N],lyd[N],f[N][15];bool bz[M],vis[M];queue<int> q;void link(int u,int v,int w){ st[++tot]=u,to[tot]=v,wei[tot]=w,next[tot]=last[u],last[u]=tot;}void spfa(){ q.push(1); bz[1]=1; memset(dis,60,sizeof(dis)); dis[1]=0; while(!q.empty()) { int u=q.front();q.pop(); bz[u]=0; efo(i,u) { int v=to[i]; if(dis[u]+wei[i]<dis[v]) { dis[v]=dis[u]+wei[i]; if(!bz[v]) { bz[v]=1; q.push(v); } } } }}void rt(int i,int t){ ++num; while(1) { int v=to[i]; if(to[i]!=t && st[i]!=t) { bz[i]=bz[i^1]=1; link(v,t,0),link(t,v,0); } val[num]+=wei[i]; if(st[i]!=t) lyd[st[i]]=num; if(st[i]==t) break; i=from[st[i]]; }}void dfs1(int v,int fr){ dfn[v]=++now; efo(i,v) { int u=to[i]; if(u==fr || bz[i]) continue; if(!dfn[u]) { from[u]=i,di[u]=di[v]+wei[i]; dfs1(u,v); } else if(dfn[u]<dfn[v]) rt(i,u); }}void dfs2(int v,int fr,int k){ vis[v]=1; dep[v]=k,f[v][0]=fr; efo(i,v) { int u=to[i]; if(bz[i] || u==fr || vis[u]) continue; dfs2(u,v,k+1); }}int getlca(int &u,int &v){ if(dep[u]>dep[v]) swap(u,v); fd(i,int(log2(dep[v])),0) if(dep[f[v][i]]>=dep[u]) v=f[v][i]; if(u==v) return u; fd(i,int(log2(dep[v])),0) if(f[u][i]!=f[v][i]) u=f[u][i],v=f[v][i]; return f[u][0];}int main(){ int _,x,y,u,v,w; scanf("%d %d %d",&n,&m,&_); tot=1; fo(i,1,m) { scanf("%d %d %d",&u,&v,&w); link(u,v,w),link(v,u,w); } spfa(); dfs1(1,1); dfs2(1,1,1); fo(j,1,int(log2(n))) fo(i,1,n) f[i][j]=f[f[i][j-1]][j-1]; while(_--) { scanf("%d %d",&x,&y); int lca=getlca(u=x,v=y); if(lyd[u] && lyd[v] && lyd[u]==lyd[v]) { int k=abs(di[u]-di[v]); k=min(k,val[lyd[u]]-k); printf("%d\n",dis[x]+dis[y]-dis[u]-dis[v]+k); } else printf("%d\n",dis[x]+dis[y]-2*dis[lca]); } return 0;}
0 1
- [JZOJ 3395] Freda的传呼机
- jzoj3395 Freda的传呼机
- Freda的传呼机
- [bzoj3047] Freda的传呼机
- 【NOIP2013模拟】Freda的传呼机
- 【NOIP2013模拟】Freda的传呼机
- 【BZOJ3047&2125】Freda的传呼机
- bzoj3047: Freda的传呼机&bzoj2125: 最短路
- JZOJ3395. 【NOIP2013模拟】Freda的传呼机
- 【NOIP2013模拟】Freda的传呼机 题解+代码
- [JZOJ3395]【NOIP2013模拟】Freda的传呼机
- Freda的传呼机 倍增LCA+dfs判环
- BZOJ 2125 最短路 && BZOJ 3047 Freda的传呼机【仙人掌最短路
- 传呼机
- wiki Freda的道路
- Freda的道路
- Freda的道路
- 【Tyvj1922】Freda的迷宫
- Ajax教程一用户名是否被注册
- Qt之自定义布局管理器(QBorderLayout)
- hdu1498 50 years, 50 colors(最小顶点覆盖)
- 软件设计模式、目标、原则
- Java设计模式(六):适配器模式Adapter
- [JZOJ 3395] Freda的传呼机
- ubuntu14.04设置静态ip
- CityMaker学习教程05 模型导入
- Mac终端(Terminal)自定义颜色,字体,背景
- hibernate缓存:一级缓存和二级缓存
- 莫比乌斯反演—详解
- hdoj1495简单BFS
- STL标准入门汇总
- Spring之AOP(学习笔记)