2611 小Biu看电影
- 1.0 秒
- 262,144.0 KB
- 20 分
- 3级题
无聊的小Biu来到了电影之城,他发现这里有n个电影院,而且每个电影院的电影票价是不同的,有一些电影院之间有双向联通的道路,想要通过某条道路也有不同的花费,小Biu想知道,他以每一个电影院为起点(当然也可以原地不动),最少需要多少花费可以看到电影。
收起
输入
第1行:两个整数n,m,n表示城市中电影院的个数,m表示电影院之间的道路总数。(1<=n<=100000,1<=m<=300000) 第2行:n个正整数,第i个正整数表示在第i个电影院看电影的票价val[i]。(1<=val[i]<=1000) 第3~m+2行:每行三个正整数,u,v,w,表示电影院u与电影院v之间有一条花费为w的道路。(1<=u,v<=n,1<=w<=1000)
输出
输出n行每行一个正整数。 第i行输出的正整数表示从第i个电影院出发,最少需要多少花费可以看到电影。
输入样例
4 4 1 2 3 4 1 2 3 2 3 4 1 3 1 1 4 1
输出样例
1 2 3 3
每一个点有有点值,边有边的权值,建立一个超级源点,超级源点和各个点相连,权值为各个点的点值,这样就相当于超级源点到各个点的最短路径,即为答案。
#include<bits/stdc++.h>
#define IL inline
#define RI register int
#define N 200000+200
#define clear(a) memset(a,0,sizeof a)
#define rk for(RI i=1;i<=n;i++)
#define ll long long
using namespace std;
const int maxn=100000+66;
const ll mod=1e9+7;
IL void read(int &x)
{
int f=1;
x=0;
char s=getchar();
while(s>'9'||s<'0')
{
if(s=='-')
f=-1;
s=getchar();
}
while(s<='9'&&s>='0')
{
x=x*10+s-'0';
s=getchar();
}
x*=f;
}
int n,m,root,T,nums;
struct code
{
int u,v,w;
} edge[N];
bool vis[N];
int head[N],tot,dis[N],cnt[N];
IL void add(int x,int y,int z)
{
edge[++tot].u=head[x];
edge[tot].v=y;
edge[tot].w=z;
head[x]=tot;
}
IL bool spfa(int now)
{
rk vis[i]=false,dis[i]=2147483647,cnt[i]=false;
queue<int>q;
q.push(now);
vis[now]=true;
dis[now]=0;
while(!q.empty())
{
int u=q.front();
q.pop();
vis[u]=false;
if(cnt[u]>=n)
return true;
for(RI i=head[u]; i; i=edge[i].u)
{
if(dis[edge[i].v]>dis[u]+edge[i].w)
{
dis[edge[i].v]=dis[u]+edge[i].w;
if(!vis[edge[i].v])
{
q.push(edge[i].v);
vis[edge[i].v]=true;
cnt[edge[i].v]++;
if(cnt[edge[i].v]>=n)
return true;
}
}
}
}
return false;
}
int a[N];
int main()
{
read(n),read(m);
tot=0;
clear(head);
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
for(RI i=1,u,v,w; i<=m; i++)
{
read(u),read(v),read(w);
add(u,v,2*w);
add(v,u,2*w);
}
for(int i=1;i<=n;i++)
{
add(0,i,a[i]);
add(i,0,a[i]);
}
spfa(0);
int ans=0;
for(int i=1; i<=n; i++)
{
printf("%d\n",dis[i]);
}
}