题意:
就是给你n点m个边,每条边被其中一个公司管理,现在你从一号点开始出发,对于到达任意一点有很多条路径,你会选择最短的路径,同时对于多个最短的路径选花费最少的那个。对于花费的计算就是,你走的这条路径,每条边走过的次数✖这条边属于那个公司的权值。
思考:
对于从1到任一点的最短路很明显,就是一遍spfa就行了。但是对于到某一点如何确定权值最小的怎么找呢。其实看到数据范围n为50,就可以发现,可以直接爆搜,但是要注意,只有dist[spot]==dist[now]+1的时候,才可以过去,为什么呢,既然是最短路,肯定从这个点走一次就到达了另一个点。这样就不会超时了,虽然n是50。但是还是超时呢,因为开longlong了,所以尽量不开long long的还是不开把。
代码:
int T,n,m,k;
int va[N];
int dist[N],vis[N];
int cnt[N],anw[N];
vector<PII > e[N];
void spfa()
{
for(int i=1;i<=n;i++) dist[i] = inf;
queue<int > q;
q.push(1);
dist[1] = 0;vis[1] = 1;
while(q.size())
{
auto now = q.front();
q.pop();
vis[now] = 0;
for(auto t:e[now])
{
int spot = t.fi;
if(dist[spot]>dist[now]+1)
{
dist[spot] = dist[now]+1;
if(!vis[spot])
{
vis[spot] = 1;
q.push(spot);
}
}
}
}
}
void dfs(int now,int sum)
{
anw[now] = min(anw[now],sum);
for(auto t:e[now])
{
int spot = t.fi,id = t.se;
if(dist[spot]==dist[now]+1)
{
cnt[id]++;
dfs(spot,sum+cnt[id]*va[id]);
cnt[id]--;
}
}
}
signed main()
{
IOS;
cin>>n>>m;
for(int i=1;i<=m;i++) cin>>va[i];
for(int i=1;i<=m;i++)
{
int a,b,c;
cin>>a>>b>>c;
e[a].pb({b,c});
e[b].pb({a,c});
}
spfa();
for(int i=1;i<=n;i++) anw[i] = inf;
dfs(1,0);
for(int i=2;i<=n;i++) cout<<anw[i]<<"\n";
return 0;
}
总结:
多多思考和总结。