spfa-codevs1021题解

玛丽卡codes 1021

题目描述 Description

麦克找了个新女朋友,玛丽卡对他非常恼火并伺机报复。

因为她和他们不住在同一个城市,因此她开始准备她的长途旅行。

在这个国家中每两个城市之间最多只有一条路相通,并且我们知道从一个城市到另一个城市路上所需花费的时间。

麦克在车中无意中听到有一条路正在维修,并且那儿正堵车,但没听清楚到底是哪一条路。

无论哪一条路正在维修,从玛丽卡所在的城市都能到达麦克所在的城市。

玛丽卡将只从不堵车的路上通过,并且她将按最短路线行车。

麦克希望知道在最糟糕的情况下玛丽卡到达他所在的城市需要多长时间

这样他就能保证他的女朋友离开该城市足够远。

编写程序,帮助麦克找出玛丽卡按最短路线通过不堵车道路到达他所在城市所需的最长时间(用分钟表示)。

输入描述 Input Description

第一行有两个用空格隔开的数N和M,分别表示城市的数量以及城市间道路的数量。1≤N≤1000,1≤M≤N*(N-1)/2

。城市用数字1至N标识,麦克在城市1中,玛丽卡在城市N中。

接下来的M行中每行包含三个用空格隔开的数A,B和V。其中1≤A,B≤N,1≤V≤1000。

这些数字表示在A和城市B中间有一条双行道,并且在V分钟内是就能通过。

输出描述 Output Description

输出文件的第一行中写出用分钟表示的最长时间,在这段时间中,无论哪条路在堵车,玛丽卡应该能够到达麦克处,如果少于这个时间的话,

则必定存在一条路,该条路一旦堵车,玛丽卡就不能够赶到麦克处。

样例输入 Sample Input

5 7

1 2 8

1 4 10

2 3 9

2 4 10

2 5 1

3 4 7

3 5 10

样例输出 Sample Output

27

初读题目,告诉我们,女朋友有风险,耍朋友须谨慎。

如果你还是没有思路,或者是迷迷糊糊。应该哦。多读几遍题。

而这道题说的是。最短路线里面的最长时间。其实意思就是删除一条边,之后找最短路径。

所有找到每一条最短路径里的时间最长的。

每删一条边,都要spfa一边找到最短的路径。之后比较。

这也算一道很裸的题。不过。这里的难点在语文。要理解

帮助麦克找出玛丽卡按/最短路线/通过不堵车道路/到达他所在城市所需的/最长时间

而代码实现,其实就是最开始一遍spfa。用h数组来记录,当前的点在松弛时,最优的那条边。记录边!!之后从终点开始,往回找。由于h里有当前节点前面的边。所以可以找到这个图的最短路径。之后呢,删最短路径就是保证最短路的整体还是有就是堵车的时候不能走最短路,最后也要步走这条边也要找到最短路。而且找的时候专除小的边,有点贪心的味道。就是这样。

#include<cstdio>
#include<string.h>
#include<algorithm>
using namespace std;
struct node{
    int next,v,t,val;
}edge[10000000];
int heads[1000000],d[1010],cnt,head,last,visit[1010],h[1010];
int q[10001];//手写队列
int n,m;
int add(int x,int y,int z)//领接表,里面有起点!这个重要。
{
    edge[++cnt].next=heads[x];
    edge[cnt].v=y;
    edge[cnt].t=x;
    edge[cnt].val=z;
    heads[x]=cnt;
}
int spfa(int x)
{
    memset(d,2147,sizeof(d));
    d[1]=0;
    int t=edge[x].val;
    edge[x].val=0xffff;//删边
    head=1;
    last=1;
    q[last]=1;
    visit[1]=1;
    while(head<=last)
    {
        int a=q[head];
        for(int i=heads[a];i!=-1;i=edge[i].next)
        {
            if(d[edge[i].v]>d[a]+edge[i].val)
            {
                if(!visit[edge[i].v]){
                    q[++last]=edge[i].v;
                    visit[edge[i].v]=0;
                    d[edge[i].v]=d[a]+edge[i].val;
                }
                else{
                    d[edge[i].v]=d[a]+edge[i].val;
                }
            }
        }
        head++;
        visit[a]=0;
    }
    edge[x].val=t;
}
int main()
{
    memset(d,2147,sizeof(d));
    memset(heads,-1,sizeof(heads));
    int x,y,z;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d%d",&x,&y,&z);
        add(x,y,z);
        add(y,x,z);
    }
    head=1;
    last=1;
    q[last]=1;
    visit[1]=1;
    d[1]=0;
    while(head<=last)
    {
        int a=q[head];
        for(int i=heads[a];i!=-1;i=edge[i].next)
        {
            if(d[edge[i].v]>d[a]+edge[i].val)
            {
                if(!visit[edge[i].v]){
                    q[++last]=edge[i].v;
                    visit[edge[i].v]=0;
                    d[edge[i].v]=d[a]+edge[i].val;
                    h[edge[i].v]=i; //记录每个点最短路松弛时的边
                }
                else{
                    d[edge[i].v]=d[a]+edge[i].val;
                    h[edge[i].v]=i;//同上
                }
            }
        }
        head++;
        visit[a]=0;
    }
    int b=d[n];
    for(int i=n;i!=1;i=edge[h[i]].t)//枚举从终点一直到起点,删最短路的一条边。
    {
        spfa(h[i]);
        b=max(b,d[n]);
    }
    printf("%d",b);
    return 0;
}
时间: 2024-12-16 16:25:54

spfa-codevs1021题解的相关文章

POJ 3259 Wormholes SPFA算法题解

本题其实也可以使用SPFA算法来求解的,不过就一个关键点,就是当某个顶点入列的次数超过所有顶点的总数的时候,就可以判断是有负环出现了. SPFA原来也是可以处理负环的. 不过SPFA这种处理负环的方法自然比一般的Bellman Ford算法要慢点了. #include <stdio.h> #include <string.h> #include <limits.h> const int MAX_N = 501; const int MAX_M = 2501; const

Codevs1021题解---SPFA+路径记录

题目描述 Description 麦克找了个新女朋友,玛丽卡对他非常恼火并伺机报复. 因为她和他们不住在同一个城市,因此她开始准备她的长途旅行. 在这个国家中每两个城市之间最多只有一条路相通,并且我们知道从一个城市到另一个城市路上所需花费的时间. 麦克在车中无意中听到有一条路正在维修,并且那儿正堵车,但没听清楚到底是哪一条路.无论哪一条路正在维修,从玛丽卡所在的城市都能到达麦克所在的城市. 玛丽卡将只从不堵车的路上通过,并且她将按最短路线行车.麦克希望知道在最糟糕的情况下玛丽卡到达他所在的城市需

【BZOJ】1486 [HNOI2009]最小圈

[算法]二分+spfa [题解]据说这个叫分数规划? 0-1分数规划 二分答案a,则对于任意的环有w/k≤a即w-ak≤0,若满足条件则a变小,否则a变大. 因为w=w1+w2+...+wk,所以变形为(w1-a)+(w2-a)+...+(wk-a)≤0.于是问题转化为在图中找负环. 不过由于spfa限制,"="没办法并入"<",但是由于精度足够,最后也就是1.00000000001≈1.00000000. 使用DFS的spfa:可以在发现更新到之前更新过的节

【日常学习】【SPFA负环+数组模拟链表实现】codevs2645 Spore题解

之前刚刚写了一道"香甜的黄油",是USACO的经典题目了.那道题用SPFA怎么找都过不了,看着别人的PAS轻松过各种拙计.黄学长说最佳方案应当是堆优化的dij,我还没有血,等学了那个之后再写黄油题解吧. 题目: 题目描述 Description 在星系1 的某颗美丽的行星之上.某陈将去标号为N 的星系,从星系g1 到达g2,某陈需要花费c1 的代价[主要是燃料,另外还有与沿途Grox 的势力作战的花费],c1 小于0 则是因为 这样的星系旅行,会给某陈带来收益[来源于物流差价,以及一些

[BZOJ 1179]ATM题解 Tarjan缩点+SPFA

[BZOJ 1179]ATM题解 Tarjan缩点+SPFA Description Input 第一行包含两个整数N.M.N表示路口的个数,M表示道路条数.接下来M行,每行两个整数,这两个整数都在1到N之间,第i+1行的两个整数表示第i条道路的起点和终点的路口编号.接下来N行,每行一个整数,按顺序表示每个路口处的ATM机中的钱数.接下来一行包含两个整数S.P,S表示市中心的编号,也就是出发的路口.P表示酒吧数目.接下来的一行中有P个整数,表示P个有酒吧的路口的编号 Output 输出一个整数,

Codevs1021玛丽卡题解

http://codevs.cn/problem/1021/ 题目大意 在一张无向图中求删去一条边后的从点1到点n的最短路的最大值. 点数≤1000,边数≤106. 题解 一开始的思路是枚举所有边,然后分别跑最短路,然后妥妥地T. 先考虑不删边的情况,那么可以跑一次最短路.(众:废话!) 然而我们的目的是把这一条最短路记录下来.实际上,要删的边都在最短路上.(否则删了一条不在最短路上的边,跑出来最短路不和没删边一样吗?) 然后就可以spfa或者dijkstra堆优化了. 实测spfa800ms+

[题解]UVa 12661 Funny Car Racing - spfa

很简单的一道最短路问题.分情况处理赛道的打开和关闭. Code 1 /** 2 * UVa 3 * Problem#12661 4 * Accepted 5 * Time:50ms 6 */ 7 #include<iostream> 8 #include<fstream> 9 #include<sstream> 10 #include<cstdio> 11 #include<cstdlib> 12 #include<cstring>

算法描述》关于SPFA和Dijkstra算法的两三事

本来我是想把这两个算法分开写描述的,但是SPFA其实就是Dijkstra的稀疏图优化,所以其实代码差不多,所以就放在一起写了. 因为SPFA是Dijkstra的优化,所以我想来讲讲Dijkstra. 什么是Dijkstra Dijkstra是一种求单源最短路的基础算法,时间复杂度在不加堆优化的情况下是o(n^2)的,加了堆优化就能简化到o(nlogn),而且算法稳定性很强(从这点上来说比SPFA好多了,具体怎么好下面再讲),基础思路如下: 首先,把所有点到源的距离设为最大,然后把源加入队列,接着

SPFA+寻路(行路难,洛谷2832)

啊啊啊这道难题总算是做出来了,首先是帅比浮云的题解发出来一下:http://www.cnblogs.com/fuyun-boy/p/5922742.html 原题目地址:https://www.luogu.org/problem/show?pid=2832 题目背景 小X来到了山区,领略山林之乐.在他乐以忘忧之时,他突然发现,开学迫在眉睫 题目描述 山区有n座山.山之间有m条羊肠小道,每条连接两座山,只能单向通过,并会耗费小X一定时间. 小X现在在1号山,他的目的是n号山,因为那里有火车站. 然

Victor and World(spfa+状态压缩dp)

题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=5418 Victor and World Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 262144/131072 K (Java/Others)Total Submission(s): 958    Accepted Submission(s): 431 Problem Description After trying hard fo