hdu1535(Dijkstra)

本文探讨了使用Dijkstra算法解决在给定数据范围内,将N个人从一个车站分配到N个车站并返回的最小成本问题。通过正向和反向构建图两次Dijkstra操作,最终计算总成本。

题目的意思是有N个车站,N个人,将N个人从一个车站分配到N个车站去,再让他们回到这个车站。交通系统全部是单项的。求总花费最小。

一开始想到FLoyd,但看了数据范围,发现做不了,后来想到做两遍Dijkstra

思路是,求一遍某个点出发的单源最短路,再将图反向,再求一边这个点的单源最短路。两遍的结果保存到两个数组,最后将两个数组中的所有值全部相加然后输出。

原理是第一遍求得从一个点出发到其他所有点的最短路径也就是最小花费,将图反转之后再求一遍,求出的是从所有其他点到这个点的最短路,(最新小花费)。

下面代码在服务器上能过,但在自己电脑上测试时需要将long long 改为int,或者缩小MaxN的值,因为本机申请不到这么大的数组。

#include <iostream>
#include <memory.h>
#include <vector>
#include <queue>
#include <stdio.h>
#define MaxN 1000005
#define INF 1000000
struct node
{
    int e,w;
    node(int ee,int ww):e(ee),w(ww) {}
    node(){}
    bool friend operator<(node n1,node n2)
    {
        return n1.w>n2.w;
    }
};

using namespace std;
int N,M;
void Dijistra(vector<vector<node> > v,long long dist[MaxN])
{
    for(int i=1;i<=N;i++)
        dist[i]=INF;
    dist[1]=0;
    priority_queue<node> Q;
    Q.push(node(1,0));
    while(!Q.empty())
    {
        node now=Q.top();
        Q.pop();
        int S=now.e;
        for(int i=0;i<v[S].size();i++)
        {
            int E=v[S][i].e;
            if(dist[S]+v[S][i].w<dist[E])
            {
                dist[E]=dist[S]+v[S][i].w;
                Q.push(node(E,dist[E]));
            }
        }
    }
}
void output(long long dist1[MaxN],long long dist2[MaxN])
{
    long long ans=0;
    for(int i=1;i<=N;i++)
        ans+=(dist1[i]+dist2[i]);
    cout<<ans<<endl;
}
int main()
{
    vector<vector<node> > v1;
    vector<vector<node> > v2;
    long long dist1[MaxN],dist2[MaxN];
    int a,b,c;
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&N,&M);
        v1.clear();v1.resize(N+1);
        v2.clear();v2.resize(N+1);
        while(M--)
        {
            scanf("%d%d%d",&a,&b,&c);
            v1[a].push_back(node(b,c));
            v2[b].push_back(node(a,c));
        }
        Dijistra(v1,dist1);
        Dijistra(v2,dist2);
        output(dist1,dist2);
    }
    return 0;
}

  

 

转载于:https://www.cnblogs.com/modengdubai/p/4746574.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值