2725: [Violet 6]故乡的梦

Time Limit: 20 Sec  Memory Limit: 128 MB
Submit: 678  Solved: 204
[Submit][Status][Discuss]

Description

Input

Output

Sample Input

6 7
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

7
6
Infinity
7

HINT

Source

interviewstreet--Going office

想法:

先跑出一条最短路径(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]故乡的梦 最短路+线段树的更多相关文章

  1. [原博客] BZOJ 2725 : [Violet 6]故乡的梦

    这个题在bzoj上好像是个权限题,想做的可以去Vani的博客下载测试数据.这里有题面. 简单叙述一下题意:给你一个n个点.m条边的带权无向图,S点和T点,询问Q次删一条给定的边的S-T最短路. 其中  ...

  2. BZOJ 2725 [Violet 6]故乡的梦 线段树+最短路树

    \(\color{#0066ff}{ 题目描述 }\) \(\color{#0066ff}{输入格式}\) \(\color{#0066ff}{输出格式}\) \(\color{#0066ff}{输入 ...

  3. BZOJ 2725: [Violet 6]故乡的梦

    求出最短路径树,对于一个询问(x,y) 若不在树上S->T的链上,则答案不变,若在链上,考虑用一条非树边替换这条边,这条非树边必须跨越x->y这条边,线段树维护区间最小值 #include ...

  4. [luogu P3797] 妖梦斩木棒 [线段树]

    题目背景 妖梦是住在白玉楼的半人半灵,拥有使用剑术程度的能力. 题目描述 有一天,妖梦正在练习剑术.地面上摆放了一支非常长的木棒,妖梦把它们切成了等长的n段.现在这个木棒可以看做由三种小段构成,中间的 ...

  5. BZOJ.5249.[九省联考2018]iiidx(贪心 线段树)

    BZOJ LOJ 洛谷 \(d_i\)不同就不用说了,建出树来\(DFS\)一遍. 对于\(d_i\)不同的情况: Solution 1: xxy tql! 考虑如何把这些数依次填到树里. 首先对于已 ...

  6. 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 ...

  7. bzoj 1645: [Usaco2007 Open]City Horizon 城市地平线【线段树+hash】

    bzoj题面什么鬼啊-- 题目大意:有一个初始值均为0的数列,n次操作,每次将数列(ai,bi-1)这个区间中的数与ci取max,问n次后元素和 离散化,然后建立线段树,每次修改在区间上打max标记即 ...

  8. BZOJ2725 : [Violet 6]故乡的梦

    如果S==T,那么答案为0. 如果S与T不连通,那么答案为inf. 否则,S到T的最短路径上至少有一条边. 求出以S为源点的最短路图,是个DAG,随便抓一条S到T的最短路,记为P. 设dpS[x]表示 ...

  9. 【BZOJ 3524】【Poi2014】Couriers 可持久化线段树

    为什么这个主席树叫可持久化线段树,我不知道,具体得问达神.我无限T,然后DaD3zZ一针见血地指出了我的N*50爆内存导致无限编译超时O)ZO)ZO)Z真是太神啦.以图为鉴: 达神题解传送门:http ...

随机推荐

  1. linux忘记登陆密码的两种破解办法

    对于使用grub引导的linux系统.在开机自检后,出现grub引导界面时,按E键进入编辑模式,如下图所示:   把光标移到带有“kernel”字样的那一行,然后按E键编辑,如图:   在末尾按一个空 ...

  2. LeetCode: 598 Range Addition II(easy)

    题目: Given an m * n matrix M initialized with all 0's and several update operations. Operations are r ...

  3. OVS编译

    下载源码 # git clone https://github.com/openvswitch/ovs.git # cd ovs # git checkout branch-2.8 下载依赖包 # y ...

  4. header元素 footer元素 hgroup元素

    header元素 header元素是一种具有引航和导航作用的结构元素, 通常用来放置整个页面或页面内的一个内容区块的标题, 但是也可以包含其他内容, 例如数据表格,搜索表单, 或相关的logo图片 h ...

  5. SVN版本控制图标未显示或显示异常解决方法

    SVN版本控制图标未显示问题解决方法,刚开始遇到这个问题的时候,好苦恼.经过“千辛万苦”的努力,终于得以解决,分享给大家,希望能帮到各位哦! 工具/原料   SVN安装包 方法/步骤     首先安装 ...

  6. 2015 Noip提高组 Day2

    P2678 跳石头 [题目背景] 一年一度的“跳石头”比赛又要开始了! [题目描述] 这项比赛将在一条笔直的河道中进行,河道中分布着一些巨大岩石.组委会已经选择好了两块岩石作为比赛起点和终点.在起点和 ...

  7. MySQL 5.7 Performance Schema 详解

    refman mysql 5.7 MySQL Performance Schema  用于监视MySQL服务器,且运行时消耗很少的性能.Performance Schema 收集数据库服务器性能参数, ...

  8. 基于 Laravel Route 的 ThinkSNS+ Component

    这里是传送门: <ThinkSNS+ 基于 Laravel master 分支,从 1 到 0,再到 0.1[ThinkSNS+研发日记系列一]> <基于 Laravel 开发 Th ...

  9. TensorBoard计算加速

    目录 TensorBoard计算加速 0. 写在前面 1. TensorFlow使用GPU 2. 深度学习训练并行模式 3. 多GPU并行 4. 分布式TensorFlow 4.1 分布式Tensor ...

  10. TPU的相关资料

    1.谷歌 TPU 的强大与局限:TPU/GPU/CPU性能功耗全面对比:http://www.sohu.com/a/134315786_473283 2.谷歌发布TPU论文,75位联合作者,GPU迎来 ...