下片 题解(最短路+超级源点)
Posted invictus-ocean
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了下片 题解(最短路+超级源点)相关的知识,希望对你有一定的参考价值。
题目描述
为了提高服务器的耐受能力,很多流量大的网站都会架设多台服务器,而互联网的路由能找到线路最短的一台服务器。 现在UOI想要下片,他有好多台电脑,又有好多服务器可以提供下载。UOI将给你一个网络图,告诉你点点之间的线路长度,问最短的线路长是多少,以及选择的那台用来下载的电脑和被选的服务器的编号。 如果有多台电脑/服务器之间连线都是最短线路,输出电脑编号最小的;如果还有多种选择,输出服务器编号最小的。
输入格式
第一行n,m,表示总格有n个点,m条网络连线 接下来m行,表示每条网络连线所连接的A、B点和线的长度。 接下来一个数T1,表示UOI有多少台电脑。 下一行T1个数,表示UOI每台电脑的编号。 接下来一个数T2,表示有多少台服务器。 下一行T2个数,表示每台服务器编号。
输出格式
三个数,分别是线路长度,UOI下载用的电脑,提供片的下载源
-------------------------------------------------------------------------------------------------------------------------
题意转化:给你一些源点和一些汇点,求一条连接源点和汇点的路径并且使得这条路径的长度最小。
使用n次spfa显然会TLE。这时候我们要引入一个概念:超级源点。意思是引入一个0号点,能连接所有源点,并且不影响原图,即长度为0。这样跑1次spfa就够。此题还要求输出源点和汇点,我们开一个pre数组,记录每个点的前驱即可(前驱指的是从哪个源点可以到达那里)。
代码中稍稍做了一点修改,本身思路与其相符。
#include<bits/stdc++.h> using namespace std; queue<int> q; struct node { int to,dis; }; vector<node> v[100005]; int n,m,t1,t2,a[100005],vis[100005],pre[100005]; long long ans=9223372036854775807,dis[100005]; int ans1,ans2; int main() { memset(dis,0x3f,sizeof(dis)); scanf("%d%d",&n,&m); for (int i=1;i<=m;i++) { int u,to,d; scanf("%d%d%d",&u,&to,&d); v[u].push_back((node){to,d}); v[to].push_back((node){u,d}); } scanf("%d",&t1); for (int i=1;i<=t1;i++) scanf("%d",&a[i]); sort(a+1,a+t1+1); scanf("%d",&t2); int t; for (int i=1;i<=t2;i++) scanf("%d",&t),pre[t]=t,vis[t]=1,dis[t]=0,q.push(t); while(!q.empty()) { int now=q.front();q.pop();vis[now]=0; for (int i=0;i<v[now].size();i++) { int to=v[now][i].to; if (dis[to]>dis[now]+v[now][i].dis) { pre[to]=pre[now]; dis[to]=dis[now]+v[now][i].dis; if (!vis[to]) vis[to]=1,q.push(to); } } } for (int i=1;i<=t1;i++) if (ans>dis[a[i]]) ans=dis[a[i]],ans1=a[i]; printf("%ld %d %d",ans,ans1,pre[ans1]); return 0; }
以上是关于下片 题解(最短路+超级源点)的主要内容,如果未能解决你的问题,请参考以下文章
hdu-2680 Choose the best route---dijkstra+反向存图或者建立超级源点
bzoj1726[Usaco2006 Nov]Roadblocks第二短路*
Codeforces Round #605 (Div. 3) E - Nearest Opposite Parity (超级源点)