BZOJ 2725: [Violet 6]故乡的梦 最短路+线段树
2725: [Violet 6]故乡的梦
Time Limit: 20 Sec Memory Limit: 128 MB
Submit: 678 Solved: 204
[Submit][Status][Discuss]
Description
.gif)
Input
.gif)
Output
.gif)
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
.gif)
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 ...
随机推荐
- NFS资料
Linux NFS服务器的安装与配置 http://www.cnblogs.com/mchina/archive/2013/01/03/2840040.html Linux NFS服务器的安装与配 ...
- CodeForces - 633B A Trivial Problem 数论-阶乘后缀0
A Trivial Problem Mr. Santa asks all the great programmers of the world to solve a trivial problem. ...
- Scrapy:Python的爬虫框架【转摘】
网络爬虫,是在网上进行数据抓取的程序,使用它能够抓取特定网页的HTML数据.虽然我们利用一些库开发一个爬虫程序,但是使用框架可以大大提高效率,缩短开发时间.Scrapy是一个使用Python编写的,轻 ...
- 交叉编译调试qemu_guest_agent
Winodws版本 编译环境Fedora23 下载VSS SDK的setup.exe 下载地址 提取VSS SDK头文件 将下面的代码保存成extract-vsssdk-headers.sh脚本,然后 ...
- php UTF8 转字节数组,后使用 MD5 计算摘要
Hex.encodeHexString(md5.digest);按 UTF8 转字节数组,后使用 MD5 计算摘要,得到 16 字节数组,使用 Hex 转为长度为 32 的字符串,保持小写 bin2h ...
- 小a和uim之大逃离(luogu P1373 dp)
小a和uim之大逃离(luogu P1373 dp) 给你一个n*m的矩阵,其中元素的值在1~k内.限制只能往下和往右走,问从任意点出发,到任意点结束,且经过了偶数个元素的合法路径有多少个.在此题中, ...
- Robot Frame应用实例讲解
关键字与变量 内置库(build in)关键字 要使用的其它库关键字(学会看文档)
- [转] iOS开发-搜索栏UISearchBar和UISearchController
原文网址: http://www.cnblogs.com/xiaofeixiang/p/4273620.html?utm_source=tuicool iOS中UISearchDisplayContr ...
- HE学业水平考试游记 By cellur925
\(I'm\) \(back\). Day -2 今天高二全体学生开始了愉悦的长达两天半的自习2333. 第一天刚了最不会的地理必修一.以前没发现,其实真的挺有趣的233. 于是用了一天学习了一年的地 ...
- javascript中的style只能取到在HTML中定义的css属性
如果在css中定义的 li{ width:100px; left:100px; top:; position:absolute; font-style:normal; } 这样执行: oli[0].s ...