图 最短路径

//最短路径:
//第一行输入 n m (n为节点数,m为边数)
//接下来输入n-1行 s t c(s头,t为尾,c为权值)
//找到最短路径
#include<iostream>
#include<vector>
#define max_size 100//这里需要优化,可计算的数据范围不够大,太大了a数组会有问题
using namespace std;
vector<int> v[max_size];//用于装下一个节点
int a[max_size][max_size];//用于装权值
long long aa[max_size]={0};//用于装从1号节点到当前节点的最优路径权值
vector<int> father[max_size];//用于装当前节点的所有父节点
int num,n;
void create_graph(int n)
{
    int i,c,b;
    for(i=0;i<n;i++)
    {
        cin>>c>>b>>a[c][b];
        v[c].push_back(b);//装入可去到的节点
        father[b].push_back(c);

    }
}
void Dijkstra(int n)//传入有向图节点,和从起点到当前节点的权值和
{
    int j,k,l;
    if(n==num)//不用往上递归特殊处理
    {
        for(j=0;j<father[n].size();j++)//1.保证其父节点已处理
        {
            if(father[n][j]==1) continue;
            if(aa[father[n][j]]==0)//该父节点还未dp处理过,向上递归,计算其最优路径
            {
                Dijkstra(father[n][j]);
            }
        }
        aa[n]=a[father[n][0]][n]+aa[father[n][0]];//选num的第一个父节点路线为基线
        for(j=1;j<father[n].size();j++)
        {
            if(a[father[n][j]][n]+aa[father[n][j]]<aa[n]) aa[n]=a[father[n][j]][n]+aa[father[n][j]];
        }
    }
    else if(n==1)//不用往上递归
    {
        for(j=0;j<v[n].size();j++)
        {
            Dijkstra(v[n][j]);
        }
    }
    else//图的中间节点
    {
        for(j=0;j<father[n].size();j++)//1.保证其父节点已处理
        {
            if(father[n][j]==1) continue;
            if(aa[father[n][j]]==0)//该父节点还未dp处理过,向上递归,计算其最优路径
            {
                Dijkstra(father[n][j]);
            }
        }
        aa[n]=a[father[n][0]][n]+aa[father[n][0]];//选第一个父节点路线为基线
        for(j=1;j<father[n].size();j++)//2.计算当前节点最优解
        {
            if(a[father[n][j]][n]+aa[father[n][j]]<aa[n]) aa[n]=a[father[n][j]][n]+aa[father[n][j]];
        }
        for(j=0;j<v[n].size();j++)//3.向下遍历
        {
            if(aa[v[n][j]]!=0) continue;//已计算过其最优解
            else
            {
                Dijkstra(v[n][j]);
            }
        }
    }
}
int main()
{
    cin>>num>>n;//num 节点数 ,n 边数
    long long res;
    create_graph(n);
    Dijkstra(1);//狄克斯特拉算法,查找最短路径
    cout<<aa[num];
    return 0;
}

优化版 dp:
例题:
问题描述
给定一个n个顶点,m条边的有向图(其中某些边权可能为负,但保证没有负环)。请你计算从1号点到其他点的最短路(顶点从1到n编号)。

输入格式
第一行两个整数n, m。

接下来的m行,每行有三个整数u, v, l,表示u到v有一条长度为l的边。

输出格式
共n-1行,第i行表示1号点到i+1号点的最短路。
样例输入
3 3
1 2 -1
2 3 -1
3 1 2
样例输出
-1
-2
数据规模与约定
对于10%的数据,n = 2,m = 2。

对于30%的数据,n <= 5,m <= 10。

对于100%的数据,1 <= n <= 20000,1 <= m <= 200000,-10000 <= l <= 10000,保证从任意顶点都能到达其他所有顶点。

#include<bits/stdc++.h>
#include<vector>

using namespace std;
#define max_size 20010

vector<int> v[max_size];//存子节点
vector<int> father[max_size];//存指向该节点的所有节点
long int res[max_size]={0};//存从起点到该节点的最短路长
vector<int> value[max_size];//存边的权值
int flag[max_size]={0};
int n,m;

void create_graph()
{
    int i,a,b,c;
    for(i=0;i<m;i++)
    {
        cin>>a>>b>>c;
        v[a].push_back(b);
        father[b].push_back(a);
        value[b].push_back(c);//权值和父节点在数组中下标的值是一样的,这里是通过索引某个节点的上层节点找最小路径,故权值也通过子节点去索引
    }
}
void dp(int num)
{
    if(num==1);
    else
    {
        int i;
        if(flag[father[num][0]]==0) dp(father[num][0]);
        res[num]=res[father[num][0]]+value[num][0];
        flag[num]=1;
        for(i=0;i<father[num].size();i++)
        {
            if(flag[father[num][i]]==0)//其父节点未处理过
            {
                dp(father[num][i]);
            }
            if(res[father[num][i]]+value[num][i]<res[num]) res[num]=res[father[num][i]]+value[num][i];
        }
    }
}
void out()
{
    int i;
    for(i=2;i<=n;i++)
    {
        if(flag[i]==0) dp(i);//通过最后一点往前找,有可能漏掉一些点
        cout<<(long)res[i]<<endl;
    }
}
int main()
{
    cin>>n>>m;
    create_graph();
    dp(n);
    out();
    return 0;
}

内存占用太大
内存占用太大

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值