【POI2004】【Bzoj2069】T2 洞穴

T2 洞穴zaw

【问题描述】

在 Byte 山的山脚下有一个洞穴入口. 这个洞穴由复杂的洞室经过隧道连接构成. 洞穴的入口是 1 号点.两个洞室要么就通过隧道连接起来,要么就经过若干隧道间接的相连. 现在决定组织办一个‘King‘s of Byteotia Cup‘ 比赛. 参赛者的目标就是任意选择一条路径进入洞穴并尽快出来即可. 一条路径必须经过除了 1 之外还至少要经过其他一个洞室.一条路径中一个洞不能重复经过(除了 1 以外),类似的一条隧道也不能重复经过.

一个著名的洞穴探险家 Byteala 正准备参加这个比赛. Byteala 已经训练了数月而且他已获得了洞穴系统的一套详细资料. 对于每条隧道他都详细计算了从两个方向经过所需要的时间. 经过一个洞室的时间很短可以忽略不记. 现在Byteala 向计算一条符合条件的最优路径.

【输入格式】

第一行有两个数 n 和 m (3 <= n <= 5000, 3 <= m <= 10000) 分别表示洞室的数目以及连接他们的隧道的数目. 洞室从 1 到 n 编号. “前面洞室”的编号为 1.接下来 m 行描述了所有的隧道. 每行四个整数 a,b,c,d 表示从洞室 a 到洞室 b 需要 c 分钟的时间,而从洞室 b 到洞室 a 需要 d 分钟的时间, 1 <= a,b <= n, a <> b, 1 <=c,d <= 10000. 你可以假设符合要求的路径肯定存在.

【输出格式】

输出一行,最少需要多少时间完成比赛.

【样例输入】

3 3

1 2 4 3

2 3 4 2

1 3 1 1

【样例输出】

6

【说明】 

经过 1,2,3,1

Solution

来源:POI2004,Bzoj2069

①O(n^2logn)

从1点出发枚举会走到哪条边哪到哪个点,将这条边回边标为不可选,从那个点跑向1的最短路即可.

因为有些奇奇怪怪的剪枝,它会跑的非常快.

剪枝:

  1. 普通单源单汇的最短路剪枝,Dijskra算法,当前更新的最小点为汇点可直接输出
  2. 枚举的那条边>=ans直接不枚举
  3. 当前最小点+W[i](枚举的那条边)>=ans可以退出
  4. 到达的点>=ans可以不入队

②%DJ两遍最短路 nlogn

一条边相当与四条边,为什么呢?双向×走法(直+倒)

edge u→v w[1]=w1(直) w[2]=w2(倒)

edge v→u w[1]=w2(直) w[2]=w1(倒)

我们拿每条边w[1](标记v→w不能)从1跑最短路,第二遍用w[2]跑,这样是从1倒着走回到其他点,相当与从其它点走过来.

统计一下每个点两次答案之和即可.

Code

// <zaw.cpp> - Thu Oct  6 08:17:54 2016
// This file is made by YJinpeng,created by XuYike‘s black technology automatically.
// Copyright (C) 2016 ChangJun High School, Inc.
// I don‘t know what this program is.

#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <queue>
#define INF 1e9
#define IN inline
#define RG register
using namespace std;
typedef long long LL;
inline int gi() {
    register int w=0,q=0;register char ch=getchar();
    while((ch<‘0‘||ch>‘9‘)&&ch!=‘-‘)ch=getchar();
    if(ch==‘-‘)q=1,ch=getchar();
    while(ch>=‘0‘&&ch<=‘9‘)w=w*10+ch-‘0‘,ch=getchar();
    return q?-w:w;
}
const int N=5010,M=N<<2;
int n,m,t,ans;int d[N],fr[N];int to[M],ne[M],W[M];bool u[N];
struct node{
    int s,p;
    bool operator<(node a)const{return s>a.s;}
};
priority_queue<node>q;
IN void link(RG int u,RG int v,RG int w){
    to[++t]=v;ne[t]=fr[u];fr[u]=t;W[t]=w;
    //if(u==1)cout<<v<<endl;this
}
void read(){
    n=gi(),m=gi();
    while(m--){
        int u=gi(),v=gi(),w=gi(),w1=gi();
        link(u,v,w);link(v,u,w1);
    }
}
IN int Dij(RG int begin,RG int end,int w){
    for(int i=1;i<=n;i++)d[i]=INF;
    q.push((node){d[begin]=0,begin});
    memset(u,0,sizeof(u));
    while(!q.empty()){
        while(u[q.top().p]&&!q.empty())q.pop();
        if(q.empty())break;
        int x=q.top().p;q.pop();u[x]=1;
        if(w+d[x]>=ans)break;//this
        if(x==end)return d[1];
        for(int o=fr[x],y;y=to[o],o;o=ne[o])
            if(d[x]+W[o]<d[y]){
                d[y]=d[x]+W[o];
                if(d[y]>=ans)continue;//this
                q.push((node){d[y],y});
            }
    }
    return d[1];
}
void Work(){
    read();ans=INF;
    for(int i=fr[1],w;i;i=ne[i]){
        if(W[i]>=ans)continue;//this
        if(i&1)w=W[i+1],W[i+1]=INF;else w=W[i-1],W[i-1]=INF;
        ans=min(ans,W[i]+Dij(to[i],1,W[i]));
        if(i&1)W[i+1]=w;else W[i-1]=w;
    }
    printf("%d",ans);
}
int main()
{
    freopen("zaw.in","r",stdin);
    freopen("zaw.out","w",stdout);
    Work();
    return 0;
}

时间: 2024-10-24 12:18:09

【POI2004】【Bzoj2069】T2 洞穴的相关文章

10.6 Graph Test

一套图论的练习题,各个方面都有挺好的 第一第二题有一定难度(来源POI),第三第四题比较水 T1 特工 szp T2 洞穴 zaw T3 最短路 line T4 最小差异值 dvalue

[BZOJ2049] [CodeVS1839] [SDOI2008] Cave 洞穴勘测 (LCT)

Description 辉辉热衷于洞穴勘测.某天,他按照地图来到了一片被标记为JSZX的洞穴群地区.经过初步勘测,辉辉发现这片区域由n个洞穴(分别编号为1到n)以及若干通道组成,并且每条通道连接了恰好两个洞穴.假如两个洞穴可以通过一条或者多条通道按一定顺序连接起来,那么这两个洞穴就是连通的,按顺序连接在一起的这些通道则被称之为这两个洞穴之间的一条路径.洞穴都十分坚固无法破坏,然而通道不太稳定,时常因为外界影响而发生改变,比如,根据有关仪器的监测结果,123号洞穴和127号洞穴之间有时会出现一条通

C# Tuple&lt;T1,T2....T&gt;元组的使用

1) 先说组元:一个数据结构,由通过逗号分割的,用于传递给一个程序或者操作系统的一系列值的组合. NET Framework 直接支持一至七元素的元组 Tuple<T1> Tuple<T1, T2> Tuple<T1, T2, T3> Tuple<T1, T2, T3, T4> Tuple<T1, T2, T3, T4, T5> Tuple<T1, T2, T3, T4, T5, T6> Tuple<T1, T2, T3, T4

3381: [Usaco2004 Open]Cave Cows 2 洞穴里的牛之二

3381: [Usaco2004 Open]Cave Cows 2 洞穴里的牛之二 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 21  Solved: 18[Submit][Status][Discuss] Description 洞窟里有一道长长的通道.它由N(1≤N≤25000)段道尾相连构成,编号分别为1到N.每个通道有一个阈值,其范围在[1,10^9]依次通过i..j的通道,那奶牛的体重指数就不能超过i..j通道中阈值的最小值.贝茜有Q

[SDOI2008]Cave 洞穴勘测

Description 辉辉热衷于洞穴勘测.某天,他按照地图来到了一片被标记为JSZX的洞穴群地区.经过初步勘测,辉辉发现这片区域由n个洞穴(分别编号为1到n)以及若干通道组成,并且每条通道连接了恰好两个洞穴.假如两个洞穴可以通过一条或者多条通道按一定顺序连接起来,那么这两个洞穴就是连通的,按顺序连接在一起的这些通道则被称之为这两个洞穴之间的一条路径.洞穴都十分坚固无法破坏,然而通道不太稳定,时常因为外界影响而发生改变,比如,根据有关仪器的监测结果,123号洞穴和127号洞穴之间有时会出现一条通

BZOJ 2929: [Poi1999]洞穴攀行

2929: [Poi1999]洞穴攀行 Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 351  Solved: 195[Submit][Status][Discuss] Description 洞穴学者在Byte Mountain的Grate Cave里组织了一次训练.训练中,每一位洞穴学者要从最高的一个室到达最底下的一个室.他们只能向下走.一条路上每一个连续的室都要比它的前一个低.此外,每一个洞穴学者都要从最高的室出发,沿不同的路走到最低的室.

判断T2是否是T1的子树

基本模仿CC150上的思路,递归地在t1中寻找能与t2的根相同的节点,作为开始比较的开始点,然后递归的比较两个树是否相等. boolean containsTree(TreeNode t1, TreeNode t2){ if(t2==null) return true; return subTree(t1,t2); } boolean subTree(TreeNode t1, TreeNode t2){ if(t1==null) return false; if(t1.val ==t2.val)

汕头市队赛 SRM1X T2 ——扫描线

绵津见-终 SRM 13 背景 "西瓜也是可以种在海上的!"--绵津见 然而种在海上的西瓜最需要防范的,是时不时会涌向瓜田的阵阵海浪. 幸好,身为海神的绵津见可以释放魔法"水平如镜"来阻止海浪拍打西瓜. 然而,当西瓜一个接一个成熟之时,它们就要离开瓜田,飘向遥远的彼岸.绵津见的魔法无法保护离开瓜田的西瓜们,但至少,也得知道西瓜们遭遇了多大的风浪啊. 描述 我们用一个坐标系来描述大海,绵津见的瓜田位于x轴下方,每当有一个西瓜成熟时,它会从x轴上一点出发,沿一条平行y轴

_bzoj2049 [Sdoi2008]Cave 洞穴勘测【LCT】

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=2049 裸的LCT,保存LCT模版.说一下出bug的几个地方叭: ①,rotate时,没有判断y是否为根,这点与普通的Splay有点差别. ②,循环变量是i,而不是x! #include <cstdio> #include <algorithm> const int maxn = 10005; int n, m, t1, t2; int ch[maxn][2], fa[maxn