P1629 邮递员送信

题目描述

有一个邮递员要送东西,邮局在节点 1。他总共要送 n−1 样东西,其目的地分别是节点 2 到节点 n。由于这个城市的交通比较繁忙,因此所有的道路都是单行的,共有 m 条道路。这个邮递员每次只能带一样东西,并且运送每件物品过后必须返回邮局。求送完这 n−1样东西并且最终回到邮局最少需要的时间。

输入格式

第一行包括两个整数,n 和 m,表示城市的节点数量和道路数量。

第二行到第 (m+1)行,每行三个整数,u,v,w,表示从 u 到 v 有一条通过时间为 w 的道路。

输出格式

输出仅一行,包含一个整数,为最少需要的时间。

输入输出样例

输入 #1

5 10
2 3 5
1 5 5
3 5 6
1 2 8
1 3 8
5 3 4
4 1 8
4 5 3
3 5 6
5 4 2

输出 #1

83

说明/提示

对于 30% 的数据,1≤n≤200。

对于 100% 的数据,1≤n≤1000,1≤m≤100000,1≤u,v≤n,1≤w≤100000,输入保证任意两点都能互相到达。

题目说明了道路是单行的,说明是有向图,所以每次回来跟去的时候不是同一条路径,所得时间也就不相同

这个题主要就是一次一对多+一次多对一     在返回时是多对一,使用逆向图将其变为一对多

ACcode:

/*
    这个题主要就是一次一对多+一次多对一  
    在返回时是多对一,使用逆向图将其变为一对多
*/
#include<bits/stdc++.h>
using namespace std;
const int inf=1e9;
int  n , m , sum ;
int dis[1005] , e[1005][1005] , ee[1005][1005] ;  //dis距离数组 e存图 ee逆向存图
void dijkstra(int mp[][1005])
{
    int vis[1005]={0}; //访问数组 未访问为0
    for(int i=1;i<=n;i++)
    {
        int u=-1 , min_dis=inf;
        for(int j=1;j<=n;j++)
        {
            if( !vis[j] && min_dis > dis[j] )  //找到两个相邻点中最短的路径下标
            {
                u=j;
                min_dis = dis[j];
            }
        }
        if(u==-1) return ;
        vis[u]=1;//在下面会对下标为u的点选择最短路径
        for(int v=1;v<=n;v++)
        {
            if( !vis[v] ) //只考虑未访问的点 好狗不吃回头草
                dis[v] = min( dis[v] , dis[u] + mp[u][v]);  //松弛操作
        }
    }
}
int main()
{
    cin>>n>>m;
    fill(e[0],e[0]+1005*1005,inf); //初始化
    fill(ee[0],ee[0]+1005*1005,inf); //初始化
    fill(dis,dis+1005,inf);  //初始化
    dis[1]=0;  //起点距离为0
    for(int i=1;i<=m;i++)
    {
        int u,v,w;
        cin>>u>>v>>w;
        e[u][v]=min(w,e[u][v]); //使用min防止重复输入,取重复输入的最小值
                                //事实上,这题给出的样例全都有重复输入
        ee[v][u]=min(w,ee[v][u]); //存一个逆向图
    }
    dijkstra(e);
    for(int i=2;i<=n;i++) sum+=dis[i];
    fill(dis,dis+1005,inf);  //重新初始化距离数组
    dis[1]=0;   //初始化起点
    dijkstra(ee);
    for(int i=2;i<=n;i++) sum+=dis[i];
    cout<<sum;
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值