BZOJ 2725: [Violet 6]故乡的梦 最短路+线段树
2725: [Violet 6]故乡的梦
Time Limit: 20 Sec Memory Limit: 128 MB
Submit: 678 Solved: 204
[Submit][Status][Discuss]
Description
Input
Output
Sample Input
1 2 1
2 3 1
3 4 2
4 5 1
5 6 1
1 3 3
4 6 3
1 6
4
1 2
1 3
4 3
6 5
Sample Output
6
Infinity
7
HINT
Source
想法:
先跑出一条最短路径(S,T),如果没删除上面的边就直接输出最短路。
如果枚举一条边(x,y),那么最短路一定能被(S-x)+(x,y)+(y,T)表示出来。所以如果要删(u,v),那就要枚举一条边(x,y),要求dis(x)<=dis(u)&&dis(y)>=dis(v),这样就保证(S,x),(y,T)不经过(u,v)了。于是按dis()顺序枚举(S,T)路径上的边,用线段树维护合法的最小值。
当然如果是有向图,就不能只用dis(x)<=dis(u)&&dis(y)>=dis(v)来限制不经过这条边了。
#include<cstdio>
#include<algorithm> typedef long long ll;
const int len(),lem();
const ll INF(0x7fffffffffffffff);
struct Node{int nd,nx,co;}bot[lem*+];int tot=,first[len+];
int flag[len+],last[len+],tmp[len+],Fr[len+],To[len+];
ll dis[len+],Go[len+],Bk[len+],ans[len+];
struct Data{int num;ll dis;}h[lem*+];int top;
struct ABC{int a,b,pos;ll c;}Edge[lem*+];
int n,m,x,y,c,S,T,Q; ll min(ll a,ll b){return a>b?b:a;}
bool cmp(Data A,Data B){return A.dis>B.dis;}
bool cmp2(ABC A,ABC B){return Go[A.a]<Go[B.a];}
void swap(int &a,int &b){if(a==b)return;a^=b;b^=a;a^=b;}
void add(int a,int b,int c){bot[++tot]=(Node){b,first[a],c};first[a]=tot;}
template <class T>void read(T &x)
{
x=;int f=;char c=getchar();
while((c<''||c>'')&&c!='-')c=getchar(); if(c=='-')f=,c=getchar();
while(c>=''&&c<=''){x=x*+c-'';c=getchar();}
x=f?-x:x;
}
struct MAP
{
ll axle[len*+]; int up;
void ins(ll x){axle[++up]=x;}
void deal()
{
std::sort(axle+,axle++up);
int _up=;//偷懒专用变量命名
for(int i=;i<=up;i++)if(axle[i]!=axle[i-])axle[++_up]=axle[i];
up=_up;
}
int two(ll x)
{
int num=up;
for(int mid,l=,r=up;l<=r;)(axle[mid=(l+r)>>]<=x)?num=mid,l=mid+:r=mid-;
return num;
}
}Map;
struct SMT
{
int nx[lem*+][],K,stot; ll small[lem*+];
void build(int &k,int L,int R)
{
k=++stot; small[k]=INF;
if(L==R)return; int MID=(L+R)>>;
build(nx[k][],L,MID),build(nx[k][],MID+,R);
}
void change(int k,int L,int R,int x,ll y)
{
small[k]=min(small[k],y); if(L==R)return; int MID=(L+R)>>;
(x<=MID)?change(nx[k][],L,MID,x,y):change(nx[k][],MID+,R,x,y);
}
ll query(int k,int L,int R,int x)
{
if(L==x)return small[k]; int MID=(L+R)>>;
return (x>MID)?query(nx[k][],MID+,R,x):
min(small[nx[k][]],query(nx[k][],L,MID,x));
}
}tree; int dfs(int x)
{
if(tmp[x])return tmp[x]; if(flag[x])return x;
tmp[last[x]]=dfs(last[x]);
return tmp[last[x]];
}
void Dij(int s,int t,int ty)
{
for(int i=;i<=n;i++)dis[i]=INF; dis[s]=;
h[top=]=(Data){s,}; Data now;
while(top)
{
now=h[],std::pop_heap(h+,h++top,cmp),top--;
while(dis[now.num]!=now.dis&&top)now=h[],std::pop_heap(h+,h++top,cmp),top--;
if(dis[now.num]!=now.dis&&!top)break;
for(int v=first[now.num];v;v=bot[v].nx)
if(dis[bot[v].nd]>now.dis+bot[v].co)
{
dis[bot[v].nd]=now.dis+bot[v].co;
last[bot[v].nd]=now.num;
h[++top]=(Data){bot[v].nd,dis[bot[v].nd]};
std::push_heap(h+,h++top,cmp);
}
}
if(ty==)
for(int v=t;v;v=last[v])flag[v]=;
if(ty==)
for(int i=;i<=n;i++)
if(dis[i]!=INF)tmp[i]=dfs(i);//O(n)
}//O(mlogm)
void Get()
{
int x=S,Ei=;
while(x!=T)
{
if(!flag[x])break;flag[x]=;
for(int v=first[x];v;v=bot[v].nx)
if(flag[bot[v].nd]&&Go[x]+bot[v].co==Go[bot[v].nd])
{
while(Go[Edge[Ei].a]<=Go[x]&&Ei<=tot)
{
if((Edge[Ei].pos^)!=v&&Edge[Ei].pos!=v&&(Edge[Ei].pos^)!=Edge[Ei-].pos)
tree.change(tree.K,,Map.up,Map.two(Go[Edge[Ei].b]),Edge[Ei].c);
Ei++;
}
ans[bot[v].nd]=tree.query(tree.K,,Map.up,Map.two(Go[bot[v].nd]));
if(ans[bot[v].nd]==INF)ans[bot[v].nd]=-;
last[bot[v].nd]=x; x=bot[v].nd;
break;
}
}
}//O(m+nlogn)
int main()
{
// freopen("C.in","r",stdin);
// freopen("C.out","w",stdout);
read(n);read(m);
for(int i=;i<=m;i++)
{
read(x),read(y),read(c);
add(x,y,c),add(y,x,c);
}
read(S),read(T);
Dij(S,T,);flag[]=;
if(dis[T]!=INF)Dij(S,T,);for(int i=;i<=n;i++)Fr[i]=tmp[i],Go[i]=dis[i],tmp[i]=;
if(dis[T]!=INF)Dij(T,S,);for(int i=;i<=n;i++)To[i]=tmp[i],Bk[i]=dis[i],tmp[i]=;
for(int i=;i<=n;i++)
for(int v=first[i];v;v=bot[v].nx)
{
Edge[v]=(ABC){i,bot[v].nd,v,};
if(Go[Edge[v].a]>Go[Edge[v].b])swap(Edge[v].a,Edge[v].b);
// if(Go[Edge[v].a]!=INF&&Bk[Edge[v].b]!=INF)
Edge[v].c=Go[Edge[v].a]+Bk[Edge[v].b]+bot[v].co;
Edge[v].a=Fr[i]; Edge[v].b=To[bot[v].nd];
if(Go[Edge[v].a]>Go[Edge[v].b])swap(Edge[v].a,Edge[v].b);
// else Edge[v].c=INF;
}
std::sort(Edge+,Edge++tot,cmp2);
for(int i=;i<=n;i++)Map.ins(Go[i]); Map.deal();
tree.build(tree.K,,Map.up);
for(int i=;i<=n;i++)last[i]=;
Get();
if(Go[T]==INF)Go[T]=-;
read(Q);
for(int i=;i<=Q;i++)
{
read(x),read(y);
if(last[x]==y)swap(x,y);
ll sum=(last[y]==x)?ans[y]:Go[T];
if(sum==-)printf("Infinity\n");else printf("%lld\n",sum);
}
return ;
}
BZOJ 2725: [Violet 6]故乡的梦 最短路+线段树的更多相关文章
- [原博客] BZOJ 2725 : [Violet 6]故乡的梦
这个题在bzoj上好像是个权限题,想做的可以去Vani的博客下载测试数据.这里有题面. 简单叙述一下题意:给你一个n个点.m条边的带权无向图,S点和T点,询问Q次删一条给定的边的S-T最短路. 其中 ...
- BZOJ 2725 [Violet 6]故乡的梦 线段树+最短路树
\(\color{#0066ff}{ 题目描述 }\) \(\color{#0066ff}{输入格式}\) \(\color{#0066ff}{输出格式}\) \(\color{#0066ff}{输入 ...
- BZOJ 2725: [Violet 6]故乡的梦
求出最短路径树,对于一个询问(x,y) 若不在树上S->T的链上,则答案不变,若在链上,考虑用一条非树边替换这条边,这条非树边必须跨越x->y这条边,线段树维护区间最小值 #include ...
- [luogu P3797] 妖梦斩木棒 [线段树]
题目背景 妖梦是住在白玉楼的半人半灵,拥有使用剑术程度的能力. 题目描述 有一天,妖梦正在练习剑术.地面上摆放了一支非常长的木棒,妖梦把它们切成了等长的n段.现在这个木棒可以看做由三种小段构成,中间的 ...
- BZOJ.5249.[九省联考2018]iiidx(贪心 线段树)
BZOJ LOJ 洛谷 \(d_i\)不同就不用说了,建出树来\(DFS\)一遍. 对于\(d_i\)不同的情况: Solution 1: xxy tql! 考虑如何把这些数依次填到树里. 首先对于已 ...
- BZOJ 2588: Spoj 10628. Count on a tree-可持久化线段树+LCA(点权)(树上的操作) 无语(为什么我的LCA的板子不对)
2588: Spoj 10628. Count on a tree Time Limit: 12 Sec Memory Limit: 128 MBSubmit: 9280 Solved: 2421 ...
- bzoj 1645: [Usaco2007 Open]City Horizon 城市地平线【线段树+hash】
bzoj题面什么鬼啊-- 题目大意:有一个初始值均为0的数列,n次操作,每次将数列(ai,bi-1)这个区间中的数与ci取max,问n次后元素和 离散化,然后建立线段树,每次修改在区间上打max标记即 ...
- BZOJ2725 : [Violet 6]故乡的梦
如果S==T,那么答案为0. 如果S与T不连通,那么答案为inf. 否则,S到T的最短路径上至少有一条边. 求出以S为源点的最短路图,是个DAG,随便抓一条S到T的最短路,记为P. 设dpS[x]表示 ...
- 【BZOJ 3524】【Poi2014】Couriers 可持久化线段树
为什么这个主席树叫可持久化线段树,我不知道,具体得问达神.我无限T,然后DaD3zZ一针见血地指出了我的N*50爆内存导致无限编译超时O)ZO)ZO)Z真是太神啦.以图为鉴: 达神题解传送门:http ...
随机推荐
- hive-0.11.0安装
一.安装 . 下载安装hive hive-0.11.0.tar.gz(稳定版) 目录:/data tar –zxvfhive-0.11.0.tar.gz . 配置 把所有 ...
- 远程访问Linux系统桌面
让Windows可以远程访问Linux系统桌面 http://jingyan.baidu.com/article/d8072ac47b810eec95cefde8.html linux系统下,11款 ...
- OVS编译
下载源码 # git clone https://github.com/openvswitch/ovs.git # cd ovs # git checkout branch-2.8 下载依赖包 # y ...
- 蓝桥杯PREV-12(dfs&割点)
题目链接:http://lx.lanqiao.cn/problem.page?gpid=T35 题意:中文题诶- 思路:dfs 假设star 和 end之间总路径数目为ans, 那么若经过路径上某点到 ...
- Android实现点击两次返回退出APP
Android实现点击两次退出APP 这两天在做一个项目碰到这么个问题,需要主界面点击两次直接退出整个APP而不是返回上一个界面,查找了网上的资料,整合和修改了一下写了这篇博客. 这里我主要以我的项目 ...
- vue+element-ui实现无限级动态菜单树
使用vue+element-ui实现无限级动态菜单 该案例实现主要使用递归的思想,递归对新人来容易迷惑的是自己调用自己,直到满足条件为止,接下来我们就一步一步实现一个动态多级菜单vue组件 搭建项目并 ...
- VRTK3.3.0-002获取手柄事件
1.首先创建VRScripts空物体,用来存放脚本,在其下创建Right空物体并添加VRTK_ControllerEvents脚本 2.Right作为右手手柄,拖拽到[VRTK_SDKManager] ...
- NOIp知识集合 By cellur925
基本算法 快速幂 ll ksm(ll a,ll b) { ll ans=; while(b) { ) ans=ans*a%p; b>>=; a=a*a%p; } return ans; } ...
- Spring Cloud与Duddo比较(非原创)
文章大纲 一.Spring Cloud与Duddo背景介绍二.Spring Cloud与Duddo比较三.参考文章 一.Spring Cloud与Duddo背景介绍 国内技术人员喜欢拿 Dub ...
- jquery中的$(this)和this
在jquery中,存在$(this)和this. 其中常见的是出现在事件处理函数中. 首先先来理解jquery对象. jquery对象其实就是DOM对象的集合. 比如:$('a')[0];------ ...