题目:3159–Candies
思路:题目先给出n个点和m条边a,b,c,来表示b比a的糖果不多于c个;相当于b - a <= c,需要求满足所有约束条件下,1号和N号两个人之间糖果数量差的最大值;
由于是求最大值,相当于求的是最短路,需要把约束条件转化为xj <= xi + k的形式。
那么b <= a + c,表示从a向b连一条长度为c的边。
源点:由于从1号点出发,一定可以到达所有边,所以1号点作为源点,求一遍最短路。
dijkstra堆优化代码:
#include <iostream>
#include <cstring>
#include <queue>
using namespace std;
typedef pair<int,int> PII;
const int N = 30010, M = 150010;
int n,m;
int h[N],w[M],e[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++;
}
void dijkstra(){
memset(dist,0x3f,sizeof dist);
dist[1] = 0;
priority_queue<PII,vector<PII>,greater<PII> > heap;
heap.push(make_pair(0,1));
while(heap.size()){
PII t = heap.top(); heap.pop();
int u = t.second, distance = t.first;
if(st[u]) continue;
st[u] = true;
for(int i = h[u]; ~i; i = ne[i]){
int j = e[i];
if(dist[j] > distance + w[i]){
dist[j] = distance + w[i];
heap.push(make_pair(dist[j],j));
}
}
}
}
int main(){
scanf("%d%d",&n,&m);
memset(h,-1,sizeof h);
for(int i = 0; i < m; i++){
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
add(a,b,c);
}
dijkstra();
printf("%d\n",dist[n]);
return 0;
}
spfa算法:
这里由于边数很大,用队列被卡时间了,因此把队列改成栈。
#include <iostream>
#include <cstring>
#include <queue>
using namespace std;
const int N = 30010, M = 150010;
int n,m;
int h[N],w[M],e[M],ne[M],idx;
bool st[N];
int dist[N],q[N];
void add(int a,int b,int c){
e[idx] = b; w[idx] = c; ne[idx] = h[a]; h[a] = idx++;
}
void spfa(){
memset(dist,0x3f,sizeof dist);
dist[1] = 0;
int tt = 1;
q[1] = 1;
while(tt){
int t = q[tt--];
st[t] = false;
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];
if(!st[j]){
q[++tt] = j;
st[j] = true;
}
}
}
}
}
int main(){
scanf("%d%d",&n,&m);
memset(h,-1,sizeof h);
for(int i = 0; i < m; i++){
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
add(a,b,c);
}
spfa();
printf("%d\n",dist[n]);
return 0;
}