赛艇表演
问题 A: 赛艇表演
题目描述
小明去某个地区观看赛艇比赛,这个地区共有n个城市和m条道路,每个城市都有赛艇比赛,在第i个城市观看赛艇表演的价钱为ai, 去其他城市观看也需要支付赛艇表演的价格。任意两个城市之间通过一条公路连接,并且道路是双向通行的, 观看赛艇比赛时经过的每一条道路都要支付一定的过路费,观看完比赛返回家时经过的每一条道路也要支付过路费。
对于每个城市u,你需要为小明确定一个城市v,使得从u出发,前往v看赛艇表演,再从v回到u,u可以等于v,要求花费的总金额尽量的少。请根据题目给出的数据输出总金额。
对于每个城市u,你需要为小明确定一个城市v,使得从u出发,前往v看赛艇表演,再从v回到u,u可以等于v,要求花费的总金额尽量的少。请根据题目给出的数据输出总金额。
输入
第一行两个正整数n和m。
接下来m行,每行三个正整数u,v,w,表示有一条双向道路连接u和v,且每经过一次的过路费是w。 接下来一行n个数,第i个数表示在第i个城市观看赛艇表演的价钱。
接下来m行,每行三个正整数u,v,w,表示有一条双向道路连接u和v,且每经过一次的过路费是w。 接下来一行n个数,第i个数表示在第i个城市观看赛艇表演的价钱。
输出
输出一行n个数,第i个数表示从第i个城市出发至少要花多少钱
样例输入
4 2
1 2 4
2 3 7
6 20 1 25
样例输出
6 14 1 25
提示
对于前30%的数据,n<=10,m<=20。
对于前50%的数据,n<=100,m<=500。
对于前70%的数据,n<=1500,m<=2000。
对于前85%的数据,图的结构以某种方式随机生成。
对于100%的数据,n<=2e5,m<=2e5,过路费和门票钱都在[1,1e12]内。
对于前50%的数据,n<=100,m<=500。
对于前70%的数据,n<=1500,m<=2000。
对于前85%的数据,图的结构以某种方式随机生成。
对于100%的数据,n<=2e5,m<=2e5,过路费和门票钱都在[1,1e12]内。
题解
一道有意思的题目,一个好点子。
最简单的想法就是暴力枚举每个点,然后spfa,这样无疑会超时。所以怎么解决超时的问题?建一个超级源点,从源点到其他每个点的距离就是观看表演的费用,因为看完表演还要回去,所以其他两点建边时直接按照两倍边权建边,然后从源点开始跑一遍spfa就可以了。只需一遍spfa!!!
1 #include<queue> 2 #include<cstdio> 3 #include<cstring> 4 #include<iostream> 5 using namespace std; 6 typedef long long LL; 7 typedef pair<int,LL> PIR; 8 const int N=202020; 9 int n,m,k; 10 LL g[N],dis[4*N]; 11 int fir[N],poi[4*N],nex[4*N]; 12 bool f[N]; 13 PIR d[N]; 14 queue<int>q; 15 void add(int x,int y,LL z) 16 { 17 nex[++k]=fir[x]; 18 fir[x]=k; 19 poi[k]=y; 20 dis[k]=z; 21 } 22 void spfa(int x) 23 { 24 d[x].second=0; 25 for(int i=fir[x];i;i=nex[i]) 26 d[poi[i]].first=poi[i], 27 d[poi[i]].second=dis[i], 28 q.push(poi[i]), 29 f[poi[i]]=1; 30 while(!q.empty()) 31 { 32 int now=q.front(); 33 f[now]=0; 34 q.pop(); 35 for(int i=fir[now];i;i=nex[i]) 36 if(d[now].second+dis[i]<d[poi[i]].second) 37 { 38 d[poi[i]].second=d[now].second+dis[i]; 39 d[poi[i]].first=d[now].first; 40 if(!f[poi[i]]) 41 { 42 q.push(poi[i]); 43 f[poi[i]]=1; 44 } 45 } 46 } 47 } 48 int main() 49 { 50 scanf("%d%d",&n,&m); 51 for(int i=1;i<=m;i++) 52 { 53 int x,y; 54 LL z; 55 scanf("%d%d%lld",&x,&y,&z); 56 add(x,y,z*2); 57 add(y,x,z*2); 58 } 59 memset(d,0x3f,sizeof(d)); 60 for(int i=1;i<=n;i++) 61 scanf("%lld",&g[i]), 62 add(0,i,g[i]), 63 add(i,0,g[i]); 64 spfa(0); 65 for(int i=1;i<=n;i++) 66 printf("%lld ",d[i].second); 67 printf("\n"); 68 return 0; 69 }