香港记者 图论

1 问题描述 众所周知,香港记者跑得比谁都快,这其中其实是有秘诀的。 首先他们会跑最短路,但是最短路会有很多条,而且其他记者也知道要跑最短路,香港记者 还统计出了每座城市带黑框眼镜的人数,如果一个记者跑路的时候城市带黑框眼镜人数的序列 字典序比另一个记者大,那么这个记者就会被不可描述的力量续走时间,导致他跑得没字典序 小的记者快。 长者日续万秒日理万机,想请你告诉他香港记者经过的总路程和城市带黑框眼镜人数的序 列,方便他找到香港记者,传授他们一些人生经验。 方便起见,设起点为 1 终点为 n。 由于续命的多样性不可描述的力量,各个城市带黑框眼镜的人数各不相同。

 

 

2 输入格式 输入文件名为 journalist.in。 第一行,两个整数 n, m 表示有 n 个城市,城市之间有 m 条有向边。 第二行,n 个数,表示每个城市带黑框眼镜的人数 bi: 接下来 m 行,每行 3 个非负整数 ui , vi , wi 表示一条有向边的起点,终点,路程。

 

 

3 输出格式 输出文件名为 journalist.out。 第一行,一个非负整数表示香港记者经过的总路程。 第二行,若干个非负整数表示香港记者经过的城市带黑框眼镜人数的序列。

 

 

4 样例 见下发/journalist/journalist.in(out)。 5 数据规模与约定 对于前 30% 的数据,2 ≤ n ≤ 2 × 103,1 ≤ m ≤ 4 × 103。 对于前 60% 的数据,保证数据随机。 对于另外 30% 的数据,保证所有起点到终点的简单路径(没有环的路径)长度相同。 对于 100% 的数据,2 ≤ n ≤ 2 × 105,1 ≤ m ≤ 4 × 105,1 ≤ w ≤ 1 × 109,存在至少一条从 起点到终点的最短路。

样例:

8 9
1 2 3 4 5 6 7 8
1 2 2
2 3 3
3 8 3
1 4 3
4 5 2
5 8 1
1 6 1
6 7 2
7 8 3

 

6
1 4 5 8

 


我们来看看这道。

首先,求最短路和路径是不用说的,但是我们要字典序最小的最短路怎么办呢?

那么我们为什么不在每次确定前驱节点的时候选出字典序最小的呢?

那么,为了保证字典序最小,我们应该从终点开始反向走向起点(反向建边),然后当几个点同时是某点的前驱节点时,我们选出最小的,就可以解答了。

代码:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define ll long long
#define il inline
#define db double
using namespace std;
il int gi()
{
    int x=0,y=1;
    char ch=getchar();
    while(ch<'0'||ch>'9')
    {
        if(ch=='-')
        y=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9')
    {
        x=x*10+ch-'0';
        ch=getchar();
    }
    return x*y;
}
il ll gl()
{
    ll x=0,y=1;
    char ch=getchar();
    while(ch<'0'||ch>'9')
    {
        if(ch=='-')
        y=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9')
    {
        x=x*10+ch-'0';
        ch=getchar();
    }
    return x*y;
}
ll point[4000045];
int head[16000045],cnt;
struct edge
{
    int next,to;
    ll lon;
}e[16000045];
il void add(int from,int to,ll lon)
{
    e[++cnt].next=head[from];
    e[cnt].to=to;
    e[cnt].lon=lon;
    head[from]=cnt;
}
int t[16000045],headd,tail=1,n;
ll dist[4000045];
int pre[4000045];
bool vis[4000045];
il void spfa()
{
    for(int i=1;i<=n;i++)
    dist[i]=1e16;
    point[0]=1e16;
    t[0]=n;
    dist[n]=0;
    while(headd!=tail)
    {
        int now=t[headd++];
        vis[now]=0;
        int r=head[now];
        while(r!=-1)
        {
            if(point[pre[e[r].to]]>point[now]&&dist[e[r].to]==dist[now]+e[r].lon)
                    pre[e[r].to]=now;
            if(dist[now]+e[r].lon<dist[e[r].to])
            {
                dist[e[r].to]=dist[now]+e[r].lon;
                pre[e[r].to]=now;
                if(!vis[e[r].to])
                {
                    vis[e[r].to]=1;
                    t[tail++]=e[r].to;
                }
            }
            r=e[r].next;
        }
    }
}
int que[100045];
int main()
{
    freopen("journalist.in","r",stdin);
    freopen("journalist.out","w",stdout);
    memset(head,-1,sizeof(head));
    n=gi();
    int m=gi(),x,y;
    ll z;
    for(int i=1;i<=n;i++)
    point[i]=gi();
    for(int i=1;i<=m;i++)
    {
        x=gi(),y=gi(),z=gl();
        add(y,x,z);
    }
    spfa();
    printf("%lld\n",dist[1]);
    for(int i=1;i!=0;i=pre[i])
    printf("%lld ",point[i]);
    return 0;
}

 

posted @ 2017-08-21 16:41  GSHDYJZ  阅读(364)  评论(0编辑  收藏  举报