POJ 1511 【heap+dij】

题意:

t组样例。

每组有n个节点,有m条单向边。

有m组输入,每组a b c 表示从a到b的单向边的权值是c。

求解,从编号为1的节点出发,有n-1个人,要求他们分别到达编号从2到n的节点再返回,所有边的权值的和最小是多少。

思路:

构图,构两个图,分别是正向图和反向图,然后用dij算单源最短路,将所有点到1的最短路加起来就是答案。

这题注意

1.inf原先的99999999定义不够大。

2.需要用到优先队列优化。

3.vector会超时,需要写手工邻接表。

4.一开始看到网上有人写getint();这样的函数发现在这道题并不能缩短时间,直接用scanf时间是1600,用了getint();时间是3200.

/*************************************************************************
       > File Name: B.cpp
       > Author: ttpond
       > Created Time: 2015-8-18 16:47:3
************************************************************************/
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
#include<math.h>
#include<vector>
#include<map>
#include<queue>
#include<stack>
#include<set>
using namespace std;
int ednum;
struct st
{
    int id,dis;
    st(int a,int b)
    {
        id=a;
        dis=b;
    }
    st(){};
};
struct cmp
{
    bool operator()(const st &a,const st &b)
    {
        return a.dis>b.dis;
    }
};
struct edge
{
    int id,w;
    edge *next;
};
edge *adj[2][1000010];
edge edges[2][1000010];
int dis[1000010];
inline void addEdge(int a,int b,int c)
{
    edge *aa,*bb;
    aa=&edges[0][ednum];
    bb=&edges[1][ednum];
    ednum++;
    aa->id=b;
    aa->w=c;
    aa->next=adj[0][a];
    adj[0][a]=aa;
    bb->id=a;
    bb->w=c;
    bb->next=adj[1][b];
    adj[1][b]=bb;
}
int n,m;
const int inf=1999999999;
int dis1[1000050];
void dfs(int num)
{
    for(int i=1;i<=n;i++)
    {
        dis[i]=inf;
    }
    priority_queue<st,vector<st>,cmp>q;
    st tmp;
    dis[1]=0;
    q.push(st(1,0));
    while(!q.empty())
    {
        tmp=q.top();
        q.pop();
        for(edge *p=adj[num][tmp.id];p;p=p->next)
        {
            if(dis[p->id]>p->w+dis[tmp.id])
            {
               dis[p->id]=p->w+dis[tmp.id];
               q.push(st(p->id,dis[p->id]));
            }
        }
    }
}int main()
{
    int t,tt;
    scanf("%d",&t);
    int a,b,c,d;
    //cout<<inf;
    for(tt=0; tt<t; tt++)
    {
        ednum=0;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
        {
            for(int j=0;j<2;j++)
            {
                adj[j][i]=NULL;
            }
        }
        for(int i=0; i<m; i++)
        {
            scanf("%d%d%d",&a,&b,&c);
            addEdge(a,b,c);
        }
        long long ans=0;
        for(int i=0;i<2;i++)
        {
            dfs(i);
            for(int i=1;i<=n;i++)
            {
                ans+=dis[i];
            }
        }
        printf("%I64d
",ans);
    }
}
原文地址:https://www.cnblogs.com/tun117/p/4749686.html