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