题目大意:
给出一个无向图,以及每头牛的位置,求所有牛到达一个点的最小花费。
Input I n p u t
3 4 5
2
3
4
1 2 1
1 3 5
2 3 7
2 4 3
3 4 5
Output O u t p u t
8
思路:
SPFA S P F A
枚举每一个点,作为牛最终的到达点,再跑一遍
SPFA
S
P
F
A
,记录最小答案即可。
时间复杂度
O(n×me),n⩽800,e⩽1450
O
(
n
×
m
e
)
,
n
⩽
800
,
e
⩽
1450
,最坏复杂度约
O(9.28×108)
O
(
9.28
×
10
8
)
。
代码:
#include <cstdio>
#include <iostream>
#include <queue>
#include <cstring>
using namespace std;
const int inf=99999999;
int dis[10001],vis[10001],head[10001],a[10001],s,ans,sum,n,m,k,t,from,to,Dis;
struct edge //邻接表
{
int next,dis,to;
}e[1000001];
void add(int from,int to ,int Dis) //建图
{
t++;
e[t].next=head[from];
e[t].to=to;
e[t].dis=Dis;
head[from]=t;
}
void spfa() //最短路
{
queue<int> q;
for (int i=1;i<=m;i++) //初始化
{
vis[i]=0;
dis[i]=inf;
}
q.push(s); //起点入队
vis[s]=1;
dis[s]=0;
while (q.size()) //相当于 while(!q.empty())
{
int u=q.front();
q.pop();
vis[u]=0;
for (int i=head[u];i;i=e[i].next) //邻接表优化
{
int v=e[i].to;
if (dis[v]>dis[u]+e[i].dis) //更新最小值
{
dis[v]=dis[u]+e[i].dis;
if (!vis[v])
{
vis[v]=1; //访问
q.push(v); //入队
}
}
}
}
}
int main()
{
ans=inf;
scanf("%d%d%d",&n,&m,&k);
for (int i=1;i<=n;i++)
scanf("%d",&a[i]);
for (int i=1;i<=k;i++)
{
scanf("%d%d%d",&from,&to,&Dis);
add(from,to,Dis);
add(to,from,Dis); //双向边
}
for (int i=1;i<=m;i++) //枚举到达点
{
s=i;
spfa();
sum=0;
for (int j=1;j<=n;j++)
sum+=dis[a[j]];
ans=min(ans,sum); //取最小值
}
printf("%d\n",ans);
return 0;
}