香港记者 图论
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; }