香甜的黄油
本题与 AcWing 1136.新年好有异曲同工之妙,都是只需要求出固定起点到其余点的最短路,然后在进行求解即可。
解题思路:
1.求出给定的N个牛所在的牧场到其余所有牧场的最短距离
2.根据每个起点到所有点的最短路,找出所有距离之和最小的点即为答案
但是要注意的是!!如果默认未连通的点的距离为 $0x3f3f3f3f$,那么在最后求解的时候谨防溢出问题,可能所有点到一个点的距离都是0x3f3f3f3f,那么这样累加之后就会出现溢出,进而出现负的Min
#include <iostream>
#include <queue>
#include <cstring>
using namespace std;
const int N = 3010, M = 600;
int n, p, c;
int h[N],ne[N],w[N],e[N],idx;
int dist[M][N];
//f数组记录的是每个牛位于哪个牧场
int f[N];
bool v[N];
int cost[N];
void add(int a,int b,int co)
{
e[idx] = b, ne[idx] = h[a], w[idx] = co, h[a] = idx ++;
}
void spfa(int i)
{
queue<int> q;
//求出当前最短路起点的下标
int No = f[i];
q.push(No);
dist[i][No] = 0;
v[No] = true;
while(q.size())
{
int t = q.front();
q.pop();
v[t] = false;
for(int k = h[t]; k != -1; k = ne[k])
{
int j = e[k];
if(dist[i][j] > dist[i][t] + w[k])
{
dist[i][j] = dist[i][t] + w[k];
if(!v[j])
{
v[j] = true;
q.push(j);
}
}
}
}
}
int main()
{
memset(cost, 0, sizeof cost);
memset(h, -1, sizeof h);
memset(dist, 0x3f, sizeof dist);
scanf("%d%d%d",&n,&p,&c);
for(int i = 0; i < n; i ++ )
{
scanf("%d",&f[i]);
}
for(int i = 0; i < c; i ++ )
{
int a,b,sp;
scanf("%d%d%d",&a,&b,&sp);
add(a,b,sp);
add(b,a,sp);
}
//求出n头牛到所有点的最短路
for(int i = 0; i < n; i ++ )
{
memset(v, 0, sizeof v);
spfa(i);
}
int Min = 0x3f3f3f3f;
for(int i = 1; i <= p; i ++ )
{
//加个标志位判断是否存在某个点不在连通域内,防止溢出产生异常
bool flag = true;
for(int j = 0 ; j < n; j ++)
{
if(dist[j][i] == 0x3f3f3f3f)
{
flag = false;
break;
}
cost[i] += dist[j][i];
}
if(flag)
Min = min(cost[i],Min);
}
cout<<Min;
return 0;
}