洛谷 P1629 邮递员送信

题目描述

有一个邮递员要送东西,邮局在节点1.他总共要送N-1样东西,其目的地分别是2~N。由于这个城市的交通比较繁忙,因此所有的道路都是单行的,共有M条道路,通过每条道路需要一定的时间。这个邮递员每次只能带一样东西。求送完这N-1样东西并且最终回到邮局最少需要多少时间。

输入输出格式

输入格式:

 

第一行包括两个整数N和M。

第2到第M+1行,每行三个数字U、V、W,表示从A到B有一条需要W时间的道路。 满足1<=U,V<=N,1<=W<=10000,输入保证任意两点都能互相到达。

【数据规模】

对于30%的数据,有1≤N≤200;

对于100%的数据,有1≤N≤1000,1≤M≤100000。

 

输出格式:

 

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

 

输入输出样例

输入样例#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
两次Dijkstra
屠龙宝刀点击就送
#include <algorithm>
#include <cstring>
#include <cstdio>

#define over() return 0;
#define inf 0x7fffffff
using namespace std;

bool vis[1001];
int n,m,i,j,dis[1001],atlas[1001][1001];
int min(int a,int b)
{
    return a>b?b:a;
}
void Dijkstra(int start)
{
    for(i=1;i<=n;++i)
    {
        dis[i]=atlas[start][i];
        vis[i]=0;
    }
    vis[start]=1;
    dis[start]=0;
    for(i=1;i<n;++i)
    {
        int minx=inf,to;
        for(j=1;j<=n;++j)
        {
            if(!vis[j]&&minx>dis[j])
            {
                minx=dis[j];
                to=j;
            }
        }
        vis[to]=1;
        for(j=1;j<=n;++j)
        {
            if(dis[j]>dis[to]+atlas[to][j])
            dis[j]=dis[to]+atlas[to][j];
        }
    }
}
int main()
{
    scanf("%d%d",&n,&m);
    int u[100001],v[100001],l[100001];
    memset(atlas,1,sizeof(atlas));
    for(i=1;i<=m;++i)
    {
        scanf("%d%d%d",&u[i],&v[i],&l[i]);
        atlas[u[i]][v[i]]=min(atlas[u[i]][v[i]],l[i]);
    }
    Dijkstra(1);
    int Answer=0;
    for(i=2;i<=n;++i)
    Answer=Answer+dis[i];
    memset(atlas,1,sizeof(atlas));
    for(i=1;i<=m;++i)
    atlas[v[i]][u[i]]=min(atlas[v[i]][u[i]],l[i]);
    Dijkstra(1);
    for(i=2;i<=n;++i)
    Answer=Answer+dis[i];
    printf("%d",Answer);
    over()
}

 


posted @ 2017-02-26 20:07  杀猪状元  阅读(267)  评论(0编辑  收藏  举报