[POI 2004]ZAW

[POI 2004]ZAW

Description

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

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

Input

第一行有两个数 和 m (3 <= n <= 5000, 3 <= m <= 10000) 分别表示洞室的数目以及连接他们的隧道的数目洞室从 到 编号. “前面洞室的编号为 1.

接下来 行描述了所有的隧道每行四个整数 a,b,c,d 表示从洞室 到洞室 需要 c分钟的时间,而从洞室 b到洞室 a需要 d分钟的时间, 1 <= a,b <= n, a <> b, 1 <= c,d <= 10000. 你可以假设符合要求的路径肯定存在

Output

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

Sample Input

3 3
1 2 4 3
2 3 4 2
1 3 1 1 

Sample Output


HINT

经过 1, 2, 3, 

题解

要求一个最短路,担心的就是一条边被正反经过两次。

规定第一步为1到i,并把这条边设为不可经过。然后从i做最短路到1,因为这个过程是不会经历重边的(如果经历了就不是最短路了)。

数据有点坑:不要标记数组还快一点...

数据有点卡SPFA:如果松弛节点时算出的dist比之前算出的最优ans还大,显然不用拓展了。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#define inf (2000000000)
using namespace std;
typedef long long lol;
int n,m,ans=inf;
struct node
{
    int next,to,dis;
}edge[20005];
int head[5005],size=1;
void putin(int from,int to,int dis)
{
    size++;
    edge[size].to=to;
    edge[size].dis=dis;
    edge[size].next=head[from];
    head[from]=size;
}
int dist[5005],vis[5005];
void SPFA(int r,int d)
{
    memset(dist,127/3,sizeof(dist));
    memset(vis,0,sizeof(vis));
    queue<int>mem;
    mem.push(r);
    vis[r]=1;
    dist[r]=0;
    while(!mem.empty())
    {
        int x=mem.front();mem.pop();
        vis[x]=0;
        for(int i=head[x];i!=-1;i=edge[i].next)
        {
            int y=edge[i].to;
            if(dist[y]>dist[x]+edge[i].dis&&dist[x]+edge[i].dis+d<ans)
            {
                dist[y]=dist[x]+edge[i].dis;
                if(!vis[y])
                {
                    vis[y]=1;
                    mem.push(y);
                }
            }
        }
    }
}
int main()
{
    freopen("zaw.in","r",stdin);
    freopen("zaw.out","w",stdout);
    int i,j;
    memset(head,-1,sizeof(head));
    memset(dist,127/3,sizeof(dist));
    scanf("%d%d",&n,&m);
    for(i=1;i<=m;i++)
    {
        int from,to,dis,dist;
        scanf("%d%d%d%d",&from,&to,&dis,&dist);
        putin(from,to,dis);
        putin(to,from,dist);
    }
    for(i=head[1];i!=-1;i=edge[i].next)
    if(edge[i].dis<ans)
    {
        int dis=edge[i].dis,distt=edge[i^1].dis;
        edge[i].dis=inf;edge[i^1].dis=inf;
        SPFA(edge[i].to,dis);
        ans=min(ans,dis+dist[1]);
        edge[i].dis=dis;edge[i^1].dis=distt;
    }
    printf("%d\n",ans);
    return 0;
}

 

posted @ 2017-08-24 15:54  kakakakakaka  阅读(303)  评论(1编辑  收藏  举报

Never forget why you start

//鼠标爆炸特效