USACO 3.2.6 香甜的黄油
SPFA+邻接表
2017年6月25日
#include<iostream>
#include<cstdio>
#include<string>
#include<algorithm>
#include<cstdlib>
#include<cmath>
#include<cstring>
using namespace std;
/*
N(1<=N<=500)只奶牛;
INPUT
第一行: 三个数:奶牛数N,牧场数(2<=P<=800),牧场间道路数C(1<=C<=1450);
第二行到第N+1行:1到N头奶牛所在的牧场号;
第N+2行到第N+C+1行:每行有三个数:相连的牧场A、B,两牧场间距离(1<=D<=255),当然,连接是双向的;
*/
int N, P, C;
struct Info_V{
int num;//这个点有的奶牛数
int fe;//邻接表第一条边
}V[900];
struct Edges{
int y, v;
int next;
}E[3000];
int tails = 0;
inline void GetEgs(int xx, int yy, int vv)
{
E[++tails].y = yy;
E[tails].v = vv;
E[tails].next = V[xx].fe;
V[xx].fe = tails;
}
void Putin()
{
cin >> N >> P >> C;
for(int i = 1; i <= N; i++){
int x; cin >> x;
V[x].num++;
}
for(int i = 1; i <= C; i++){
int a, b, t; cin >> a >> b >> t;
GetEgs(a, b, t);
GetEgs(b, a, t);
}
}
bool Jud[900];
int Dis[900];//第一条边为计算点,到任意点的最短距离。
int Que[2000];
int sr = 0, en = 1;
void SPFS(int o)
{
memset(Jud, false, sizeof(Jud));
memset(Dis, 10, sizeof(Dis));
memset(Que, 0, sizeof(Que));
sr = 0; en = 1;
Jud[o] = true; Que[1] = o; Dis[o] = 0;
while(sr < en)
{
//sgn为队列中的点,lne为sgn点的第一条边的序号,随后变为边序号;
int sgn = Que[++sr]; Jud[sgn] = false;
int lne = V[sgn].fe;
for(int i = lne; i != 0; i = E[i].next)
{
//ly为这条边的另一条节点;
int ly = E[i].y;
if(Dis[sgn] + E[i].v < Dis[ly])
{
Dis[ly] = Dis[sgn] + E[i].v;
if(!Jud[ly])
{
Que[++en] = ly;
Jud[ly] = true;
}
}
}
}
}
void SEARCH()
{
int min_Dis = 99999999;
for(int i = 1; i <= P; i++)
{
SPFS(i);
int cal = 0;
for(int k = 1; k <= P; k++)
cal += V[k].num * Dis[k];
min_Dis = min(min_Dis, cal);
}
cout << min_Dis <<endl;
}
int main()
{
Putin();
SEARCH();
return 0;
}