最短路,Dijkstra,SPFA——hdu1535

题目链接

今天集训学长没有给负环的题,所以一下子全都用Dijkstra做了,SPFA都没练习到,所以专门把这道不卡SPFA的题拿来练练

题目含义

求1到其他点的最短距离之和,加上其他点到1的最短距离之和

题目分析

求1到其他点的最短距离之和,也就是单源最短路径,Dijkstra和SPFA应该都行

而其他点到1的最短距离之和,实际上还是求的1到其他点的距离,不过由于路径两个方向的长度不一样,所以反向建树就好了

题目代码

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std;
const int maxn=1e6+7;
const int INF=0x3f3f3f3f;
typedef long long LL;
int head[maxn],dis[maxn];
int tot,u[maxn],v[maxn],w[maxn];
bool vis[maxn];
LL ans;
int t,n,m;
struct edge{
    int to,w,next;
}e[maxn];
struct node{
    int pos,dis;
    bool operator<(const node &x)const{
        return dis>x.dis;
    }
};
void add(int u,int v,int w){
    e[tot].to=v;
    e[tot].w=w;
    e[tot].next=head[u];
    head[u]=tot++;
}
void init(){
    tot=0;
    memset(dis,INF,sizeof(dis));
    memset(head,-1,sizeof(head));
    memset(vis,false,sizeof(vis));
}
void Dijkstra(){
    dis[1]=0;
    priority_queue<node>q;
    q.push((node){1,0});
    while(!q.empty()){
        node temp=q.top();q.pop();
        int u=temp.pos;
        if(vis[u])continue;
        vis[u]=true;
        for(int i=head[u];i!=-1;i=e[i].next){
            int v=e[i].to;
            if(dis[v]>dis[u]+e[i].w){
                dis[v]=dis[u]+e[i].w;
                if(!vis[v])q.push((node){v,dis[v]});
            }
        }
    }
}
int main(){
    scanf("%d",&t);
    while(t--){
        scanf("%d%d",&n,&m);
        ans=0;
        init();
        for(int i=1;i<=m;i++){
            scanf("%d%d%d",&u[i],&v[i],&w[i]);
            add(u[i],v[i],w[i]);
        }
        Dijkstra();
        for(int i=2;i<=n;i++)
            ans+=dis[i];
        init();
        for(int i=1;i<=m;i++){
            add(v[i],u[i],w[i]);
        }
        Dijkstra();
        for(int i=2;i<=n;i++)
            ans+=dis[i];
        printf("%lld
",ans);
    }
    return 0;
}
Dijkstra做法

真的是Dijkstra做多了,一遍就过了

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std;
const int maxn=1e6+7;
const int INF=0x3f3f3f3f;
typedef long long LL;
int head[maxn],dis[maxn],num[maxn];
bool vis[maxn];
LL ans;
int t,n,m,tot,u[maxn],v[maxn],w[maxn];
struct edge{
    int to,w,next;
}e[maxn];
void add(int u,int v,int w){
    e[tot].to=v;
    e[tot].w=w;
    e[tot].next=head[u];
    head[u]=tot++;
}
void init(){
    tot=0;
    memset(head,-1,sizeof(head));
    memset(vis,false,sizeof(vis));
    memset(dis,INF,sizeof(dis));
    memset(num,0,sizeof(num));
}
bool SPFA(){
    queue<int>q;
    dis[1]=0;num[1]++;vis[1]=true;
    q.push(1);
    while(!q.empty()){
        int u=q.front();q.pop();
        vis[u]=false;
        for(int i=head[u];i!=-1;i=e[i].next){
            int v=e[i].to;
            if(dis[v]>dis[u]+e[i].w){
                dis[v]=dis[u]+e[i].w;
                if(!vis[v]){
                    vis[v]=true;
                    num[v]++;
                    q.push(v);
                    if(num[v]>n)return false;
                }
            }
        }
    }
    return true;
}
int main(){
    scanf("%d",&t);
    while(t--){
        scanf("%d%d",&n,&m);
        ans=0;
        init();
        for(int i=1;i<=m;i++){
            scanf("%d%d%d",&u[i],&v[i],&w[i]);
            add(u[i],v[i],w[i]);
        }
        SPFA();
        for(int i=2;i<=n;i++)
            ans+=dis[i];
        init();
        for(int i=1;i<=m;i++){
            add(v[i],u[i],w[i]);
        }
        SPFA();
        for(int i=2;i<=n;i++)
            ans+=dis[i];
        printf("%lld
",ans);
    }
    return 0;
}
SPFA做法

我果然写的不熟练,照着模板写的

还得再练练

原文地址:https://www.cnblogs.com/helman/p/11278463.html