POJ 1511 最短路spfa

题很简单 就是有向图中求给出的源点到其余所有点的最短路的和与其余所有点到源点的最短路之和

一开始以为dij对于正权图的单源最短路是最快的 写了一发邻接表的dij 结果超时 把所有的cin改成scanf 还是超时(过去并没有用cin的坏习惯..近两个星期才开始疯狂的使用cin..因为懒..)

后来想了一下 spfa也可以求单源最短路 就试着写了一发scanf 然后wa...看了半天题目 发现是有很大可能爆int的 改了后1800+msAC 用cin仍然超时

所以cin害人不浅 scanf大法好23333333

咨询了一下学长 学长给出来一个看似很有道理的解答:dij与bel都是直接在所有直接相连的点或者是所有直接相连的边里选最优 spfa是bell的优化 所以一定程度上也是对dij的优化 spfa讲道理是可以适合两个版本的

自己思考了一下 dij是耿直的尝试更新 spfa是如果可以松弛就放入队列 于是同一个点避开了多次的尝试作为终点更新 大概是这样吧...稀疏图应该是dij更快把..

至于为什么不写堆优化的dij呢?当然是我不会了23333333333333333333333

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<map>
#include<math.h>
#include<queue>
#include<iostream>
using namespace std;
int n,m;
int t1,t2;
struct node
{
    int v;
    long long  w;
    int nex;
};
node a[1000050];
node b[1000050];
int p1[1000050];
int p2[1000050];
void add1(int u,int v,long long  w)  /// real
{
    a[t1].v=v;
    a[t1].w=w;
    a[t1].nex=p1[u];
    p1[u]=t1;
    t1++;
}
void add2(int u,int v,long long  w)  /// un
{
    b[t2].v=v;
    b[t2].w=w;
    b[t2].nex=p2[u];
    p2[u]=t2;
    t2++;
}
long long  dis1[1000050];
long long  dis2[1000050];
bool vis[1000050];
void spfa1(){
queue<int >q;
q.push(1);
vis[1]=false;
while(!q.empty()){
    int u=q.front();q.pop();
    vis[u]=true;
    for(int tt=p1[u];tt!=-1;tt=a[tt].nex)
    {
        int v=a[tt].v;
        int w=a[tt].w;
        if(dis1[u]+w<dis1[v])
        {
            dis1[v]=dis1[u]+w;
            if(vis[v])
            {
                vis[v]=false;
                q.push(v);
            }
        }
    }
}
}
void spfa2(){
queue<int >q;
q.push(1);
vis[1]=false;
while(!q.empty()){
    int u=q.front();q.pop();
    vis[u]=true;
    for(int tt=p2[u];tt!=-1;tt=b[tt].nex)
    {
        int v=b[tt].v;
        int w=b[tt].w;
        if(dis2[u]+w<dis2[v])
        {
            dis2[v]=dis2[u]+w;
            if(vis[v])
            {
                vis[v]=false;
                q.push(v);
            }
        }
    }
}
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        for(int i=1; i<=n; i++)
            dis1[i]=dis2[i]=999999999999999;
        dis1[1]=0;
        dis2[1]=0;
        for(int i=1; i<=n; i++)
            vis[i]=true;
        for(int i=1; i<=n; i++)
        {
            p1[i]=p2[i]=-1;
        }
        t1=t2=0;
        for(int i=1; i<=m; i++)
        {
            int u,v;
            long long w;
            scanf("%d%d%I64d",&u,&v,&w);
            add1(u,v,w);
            add2(v,u,w);
        }
        spfa1();
        for(int i=1; i<=n; i++)
        vis[i]=true;
        spfa2();
        long long  ans=0;
        for(int i=2;i<=n;i++)
        {
            ans+=dis1[i];
            ans+=dis2[i];
        }
        printf("%I64d\n",ans);
    }
}

  

时间: 2024-12-21 18:07:28

POJ 1511 最短路spfa的相关文章

It&amp;#39;s not a Bug, It&amp;#39;s a Feature! (poj 1482 最短路SPFA+隐式图+位运算)

Language: Default It's not a Bug, It's a Feature! Time Limit: 5000MS   Memory Limit: 30000K Total Submissions: 1353   Accepted: 516 Description It is a curious fact that consumers buying a new software product generally do not expect the software to

HDU 1535 &amp;&amp; POJ 1511 Invitation Cards (SPFA 模板 + 反向建图)

Invitation Cards HDU: Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) POJ: Time Limit: 8000 MS     Memory Limit: 262144 K       Problem Description In the age of television, not many people attend theater performa

poj 1511 Invitation Cards spfa 邻接矩阵

题目链接: http://poj.org/problem?id=1511 题目大意: 这道题目比较难理解,我读了好长时间,最后还是在队友的帮助下理解了题意,大意就是,以一为起点,求从一到其他各点的最短回路总和. 解题思路: 解决这个题目有几个容易错的,解决了离ac就不远了^_^. 1:数据范围是1<=边数<=顶点数<=1000000,所以不能用邻接矩阵,要用邻接表,用vector实现时要动态申请内存. 2:求得是起始点到其他点的最短回路和,我们可以建两个邻接表(一个正向,一个负向邻接表)

poj 2387 最短路 spfa 实现

http://poj.org/problem?id=2387 题目大意就是求最短路,从n到1的最短路.就用来熟悉一下spfa的写法. 一开始贡献了好几次wa,结果发现是因为n,m写反了.... 没有什么拐弯的地方,来熟悉spfa直接附上代码: #include <iostream> #include <cstdio> #include <cstring> #include <queue> #include <vector> using names

POJ - 1511 - 两次SPFA

这道题也算是一道模板题,但是第一次用优先队列迪杰斯特拉就T了.1e6的数据量,给了8s,网上其他题解中说要用SPFA. 题意:N个点的带权有向图.每次都从1出发,要到达其余没有被访问过的一个点(发传单?),然后返回,过程中其余被访问的点不计算在内.求整个过程走过的最短路程. 分析:用原图跑SPFA计算从源点1到其余各点的最短路,再将原图转置为反向图,对反向图再跑一遍SPFA,计算出各点到1的最短路(求各点到一个点的最短路是这么个操作). 然后求sigma(d[i]+rd[i]). #includ

POJ 3159 最短路 SPFA

#include<iostream> using namespace std; const int nMax = 30005; const int mMax = 150005; const int inf = 1000000000; struct node{ int v, w, next; }edge[mMax]; int n, edgeHead[nMax], dict[nMax]; int stack[nMax]; bool vis[nMax]; void spfa(){ for(int i

POJ 1511 Invitation Cards (最短路)

Invitation Cards Time Limit: 8000MS   Memory Limit: 262144K Total Submissions: 19215   Accepted: 6311 Description In the age of television, not many people attend theater performances. Antique Comedians of Malidinesia are aware of this fact. They wan

POJ 3268 Silver Cow Party (来回最短路 SPFA)

Silver Cow Party Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 14384   Accepted: 6490 Description One cow from each of N farms (1 ≤ N ≤ 1000) conveniently numbered 1..N is going to attend the big cow party to be held at farm #X (1 ≤X ≤

poj 1511 Dijkstra的另一种用法---求其他点到源点的最短路

传送门:http://poj.org/problem?id=1511 题目其实到现在我都没读懂,到底是哪里看出来的,ans是源点到各个点最短路的和外加各个点到源点的最短路的和,不过重要的是学到dijkstra的另一种用法--求各个点到源点的距离,原理不难理解,就是把dijkstra求单源最短路径的过程逆过来: 1.取源点加入S集合,设其余点在T集合 2.找到达源点的最小边,将该边连的点加入S,更新T到S的各个点的最短路径,取最短的边,继续2的过程 而dijastra求单源最短路径的过程 1.取源