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 ...
随机推荐
- 滴滴Booster移动APP质量优化框架 学习之旅 二
推荐阅读: 滴滴Booster移动App质量优化框架-学习之旅 一 Android 模块Api化演练 不一样视角的Glide剖析(一) 续写滴滴Booster移动APP质量优化框架学习之旅,上篇文章分 ...
- Fedora下Msitools使用
msitools学习 msitools使用 wixl-heat使用 概述 打包程序就是把程序依赖的所有库文件和可执行文件以及其他一些资源文件按照源目录结构进行压缩,知道自己的程序依赖哪些库是简单的,但 ...
- Anagram(山东省2018年ACM浪潮杯省赛)
Problem Description Orz has two strings of the same length: A and B. Now she wants to transform A in ...
- scrapy爬取数据的基本流程及url地址拼接
说明:初学者,整理后方便能及时完善,冗余之处请多提建议,感谢! 了解内容: Scrapy :抓取数据的爬虫框架 异步与非阻塞的区别 异步:指的是整个过程,中间如果是非阻塞的,那就是异步 ...
- SpringMVC之一个简单的例子
一.一个简单的例子 二.web.xml文件配置 三.spring-mvc.xml文件(等同于struts2的struts文件) 四.login.jsp(登录页面) 五.登录成功的页面(success. ...
- [Android]Android之四种常见布局
一个丰富的界面总是要由很多个控件组成的,那我们如何才能让各个控件都有条不紊地 摆放在界面上,而不是乱糟糟的呢?这就需要借助布局来实现了.布局是一种可用于放置很 多控件的容器,它可以按照一定的规律调整内 ...
- Codeforces Round #528-A. Right-Left Cipher(字符串模拟)
time limit per test 1 second memory limit per test 256 megabytes input standard input output standar ...
- codeforces597C-树状数组优化dp
因为整个序列为一个1-n的排列,所以可以这样dp dp[i][j]代表长度为i,以数字j结尾的子序列 dp[i][j]=dp[i-1][1,2,3...j-1]; 这道题的答案就是 dp[k+1][1 ...
- 1081 Rational Sum(20 分)
Given N rational numbers in the form numerator/denominator, you are supposed to calculate their sum. ...
- 线程池(1)ThreadPoolExecutor梳理
使用默认的 thread factory创建ThreadPoolExecutor实例 public ThreadPoolExecutor(int corePoolSize, int maximumPo ...