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. xgene:之ROC曲线、ctDNA、small-RNA seq、甲基化seq、单细胞DNA, mRNA

    灵敏度高 == 假阴性率低,即漏检率低,即有病人却没有发现出来的概率低. 用于判断:有一部分人患有一种疾病,某种检验方法可以在人群中检出多少个病人来. 特异性高 == 假阳性率低,即错把健康判定为病人 ...

  2. solr-建立单机版的服务器

    回到之前打开的页面,刷新,wenda就出来了: 这个wenda是单机版的.

  3. Spring入门第十六课

    接上一次讲课 先看代码: package logan.spring.study.annotation.repository; public interface UserRepository { voi ...

  4. Working Experience - NLog 多实例时配置文件冲突

    正文 问题: 当前项目已使用 NLog 的情况下再引用使用 NLog 的项目, 出现配置文件冲突, 有一个配置文件不工作 方法: 使用 LogFactory 代替 LogManager 来获取 Log ...

  5. Unity命令行打包

    http://www.66acg.com/?post=137 补充 unity编辑器端获取打包命令行自定义参数,这个可以获取到所有打包时的参数 string[] runArgs = System.En ...

  6. 解决Idea项目启动报错:程序包javax.servlet.http不存在

    报错信息 在没有使用maven的时候,web项目从远程仓库获取下以后,起一次启动往往会报错javax.servlet.http程序包找不到,随之而来的java基础包都将不能使用,报错信息如下: 解决方 ...

  7. 8.Python初窥门径(文件操作)

    Python (文件操作) 一.文件操作方式 打开文件 open 操作文件 read or write 关闭文件 close 二.打开文件的方式(第一种) 语法 : f=open("文件&q ...

  8. JS高级学习历程-7

    [面向(基于)对象] 1 创建对象 在php里边,需要先找到一个类别,在通过类创建具体对象 在javascript里边,可以直接创建具体对象,后期可以再给对象丰富许多属性或方法. 1. 字面量方式创建 ...

  9. JavaScript基础学习日志(1)——属性操作

    JS中的属性操作: 属性操作语法 属性读操作:获取 实例:获取Input值 实例:获取select值 字符串连接 属性写操作:修改.添加 实例:修改value值 实例:添加图片的src地址 inner ...

  10. 078 Subsets 子集

    给定一组不同的整数 nums,返回所有可能的子集(幂集).注意事项:该解决方案集不能包含重复的子集.例如,如果 nums = [1,2,3],结果为以下答案:[  [3],  [1],  [2],  ...