洛谷p1807 spfa算法和拓扑排序两种算法

第一种拓扑排序:

//有重边
//对入度为零的点
#include<iostream>
#include<queue>
#include<algorithm>
#include<vector>
#include<memory.h>
#define maxn 1505
using namespace std;
struct edge{
    int v,w;
};
vector<edge> s[maxn];
queue<int> q;
int mx[maxn];
int in[maxn];
int n,m;
int main(){
    cin>>n>>m;
    int x,y,z;
    for(int i=1;i<=m;i++){
        cin>>x>>y>>z;
        for(int j=0;j<s[x].size();j++)
            if(y == s[x][j].v){       //去重边
                if(s[x][j].w > z) z=s[x][j].w;
            }
        s[x].push_back((edge){y,z});
        in[y]++;
    }
    //这道题有点不一样,对于其他没有入度的点需要把对应的边去掉
    //仔细想想就知道为什么要去掉
    for(int i=1;i<=n;i++){
        if(in[i] == 0 && i !=1){
            //对于非1的入度为零的点进行top排序
            for(int j=0;j<s[i].size();j++){
                in[s[i][j].v]--;
            }
        }
    }
    mx[1]=0;mx[n]=-1;
    q.push(1);
    while(!q.empty()){
        int p=q.front();
        q.pop();
        for(int i=0;i<s[p].size();i++){
            int a=s[p][i].v;
            in[a]--;
            // if(mx[a]<mx[p]+s[p][i].w) mx[a]=mx[p]+s[p][i].w;
            mx[a]=max(mx[a],mx[p]+s[p][i].w);//上一个点的权值加边的权值
            if(in[a]==0){
                q.push(a);
                
            }
        }
    }
   
    cout<<mx[n]<<endl;
    return 0;
}

第二种:spfa算法

算法具体看:http://keyblog.cn/article-21.html

#include<iostream>
#include<queue>
#include<algorithm>
#include<vector>
#include<memory.h>
#define maxn 1505
using namespace std;
//2、spfa算法:原本是求最短路径
//只需要把权值改为负数,就可以求得最长路径
//考虑重边
#define INF 0x3f3f3f3f
int n,m;
int s[maxn];//最短路径
int t[maxn];//表示是否存在于队列中
queue<int> q;
struct edge{
    int v,w;
};
vector<edge> v[maxn];
int main(){
    int x,y,z;
    cin>>n>>m;
    for(int i=1;i<=m;i++){
        cin>>x>>y>>z;
        z=z*(-1);
        // v[x].push_back((edge){y,(-1)*z});
          for(int j=0;j<v[x].size();j++)
            if(y == v[x][j].v){       //去重边
                if(v[x][j].w < z) z=v[x][j].w;
            }
        v[x].push_back((edge){y,z});
    }
    s[1]=0;
    for(int i=2;i<=n;i++){
        s[i]=INF;
    }
    q.push(1);
    while(!q.empty()){
        int p=q.front();
        q.pop();
        t[p]=0;
        for(int i=0;i<v[p].size();i++){
            int a=v[p][i].v;
            s[a] = min(s[a],s[p]+v[p][i].w);
            if(t[a] == 0)//如果在队列中不存在
            {
                q.push(a);
                t[a]=1;
            }
            //遍历队列中是否存在a,如果存在就不入,不存在就入队列
        }
    }
    //
    int ans=s[n];
    ans=ans*(-1);
    if(s[n] == INF){
        cout<<-1<<endl;
    }
    else
    cout<<ans<<endl;
    return 0;
}

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值