<—点个赞吧QwQ
宣传一下算法提高课整理
农夫John发现了做出全威斯康辛州最甜的黄油的方法:糖。
把糖放在一片牧场上,他知道 N 只奶牛会过来舔它,这样就能做出能卖好价钱的超甜黄油。
当然,他将付出额外的费用在奶牛上。
农夫John很狡猾,就像以前的巴甫洛夫,他知道他可以训练这些奶牛,让它们在听到铃声时去一个特定的牧场。
他打算将糖放在那里然后下午发出铃声,以至他可以在晚上挤奶。
农夫John知道每只奶牛都在各自喜欢的牧场(一个牧场不一定只有一头牛)。
给出各头牛在的牧场和牧场间的路线,找出使所有牛到达的路程和最短的牧场(他将把糖放在那)。
数据保证至少存在一个牧场和所有牛所在的牧场连通。
输入格式
第一行: 三个数:奶牛数 N,牧场数 P,牧场间道路数 C。
第二行到第 N+1 行: 1 到 N 头奶牛所在的牧场号。
第 N+2 行到第 N+C+1 行:每行有三个数:相连的牧场A、B,两牧场间距 D,当然,连接是双向的。
输出格式
共一行,输出奶牛必须行走的最小的距离和。
数据范围
$1 \le N \le 500$,
$2 \le P \le 800$,
$1 \le C \le 1450$,
$1 \le D \le 255$
输入样例:
3 4 5
2
3
4
1 2 1
1 3 5
2 3 7
2 4 3
3 4 5
输出样例:
8
思路
我们枚举以当前点为起点,跑$\text{Dijkstra}$,如果有某一个点跑不到就直接返回正无穷,否则返回所有牛,的最短距离之和。
代码
#include <iostream>
#include <cstring>
#include <queue>
#include <vector>
using namespace std;
typedef pair <int,int> PII;
const int N = 810,M = 3010,INF = 0x3f3f3f3f;
int n,p,m;
int cow[N];
int h[N],e[M],w[M],ne[M],idx;
bool st[N];
int dist[N];
void add (int a,int b,int c) {
e[idx] = b;
w[idx] = c;
ne[idx] = h[a];
h[a] = idx++;
}
int dijkstra (int s) {
memset (st,false,sizeof (st));
memset (dist,0x3f,sizeof (dist));
dist[s] = 0;
priority_queue <PII,vector <PII>,greater <PII>> heap;
heap.push ({0,s});
while (!heap.empty ()) {
int t = heap.top ().second;
heap.pop ();
if (st[t]) continue;
st[t] = true;
for (int i = h[t];~i;i = ne[i]) {
int j = e[i];
if (dist[j] > dist[t] + w[i]) {
dist[j] = dist[t] + w[i];
heap.push ({dist[j],j});
}
}
}
int ans = 0;
for (int i = 1;i <= n;i++) {
if (dist[cow[i]] == INF) return INF;
ans += dist[cow[i]];
}
return ans;
}
int main () {
memset (h,-1,sizeof (h));
cin >> n >> p >> m;
for (int i = 1;i <= n;i++) cin >> cow[i];
while (m--) {
int a,b,c;
cin >> a >> b >> c;
add (a,b,c);
add (b,a,c);
}
int ans = INF;
for (int i = 1;i <= p;i++) ans = min (ans,dijkstra (i));
cout << ans << endl;
return 0;
}
Orz
基本和大佬一个代码,但是怎么一直在tle
好像是w数组的大小开错了,应该是要开成M。我也错过好几次这个。qwq
双向剪边+链式前向星要开两倍空间
谢谢,确实是这个问题,数组大小开小了
想问一下add四条语句的意思是什么啊
加边操作
tql