题目链接:kuangbin带你飞 专题四 最短路练习 K - Candies
题意
给n个人分糖果,m组数据a,b,c;意思是a比b少的糖果个数绝对不超过c个,也就是d(b)-d(a) < c,求1比n少的糖果数的最大值。
思路
也是通过这个题第一次接触到差分约束这个东西,学习了下,很奇妙。
令x-y<=z表示x最大比y大z。
若b-a<=k1, c-b<=k2, c-a<=k3,那么c-a最大为多少呢?显然应该等于min(k1+k2, k3)。可以用下图来表示示(不擅图丑勿怪)
这样的情况跟图论里的最短路极其相似,故此我们可以将其转换为对1到n的最短路求解的问题。
最短路,dijkstra,spfa都可
本人一开始用spfa+queue,直接超时,看别人题解都说是
spfa用队列维护数据会超时,用栈可以通过,果然,直接ac(这点我相当奇怪,关于栈与队列在实现spfa上的效率一直没有什么定论。为何在本体上相差这么多(一个500ms,一个1500ms还不够)。好多人说是测试数据的问题)
总之虽然用spfa+stack过了,但不知缘由的ac令人相当不舒服,所以又用dijkstra写了一遍(需要heap优化,否则也会超时)
代码
dijkstra+heap
#include<iostream>
#include<cstring>
#include<cmath>
#include<cstdio>
#include<algorithm>
#include<stack>
#include<queue>
using namespace std;
const int N = 150009;
const int MAX = 0x3f3f3f3f;
bool vis[N];
int d[N];
int ans[N] = {};
int head[N];
struct Edge
{
int u, v, w, next;
}e[N];
struct Node
{
int x, v;
Node(int a, int b): x(a), v(b) {}
bool operator < (const Node &t) const
{
return this->v > t.v;
}
};
int dijkstra(int n)
{
memset(vis, 0, sizeof(vis));
memset(d, 0x3f3f3f3f, sizeof(d));
priority_queue<Node, vector<Node> > q;
for(int i=head[1]; i!=-1; i=e[i].next)
d[e[i].v] = e[i].w;
for(int i=2; i<=n; i++)
q.push(Node(i,d[i]));
d[1] = 0;
vis[1] = 1;
for(int k=1; k<n && !q.empty(); k++)
{
Node t = Node(0, 0);
do{
t = q.top();q.pop();
}while(vis[t.x] && !q.empty());
int x = t.x;
if(x == -1)
break;
vis[x] = 1;
for(int i=head[x]; i!=-1; i=e[i].next)
{
if(!vis[e[i].v] && d[e[i].v] > d[x] + e[i].w)
{
d[e[i].v] = d[x] + e[i].w;
q.push(Node(e[i].v, d[e[i].v]));
}
}
}
return d[n];
}
int main()
{
int n, m;
while(~scanf("%d%d", &n, &m))
{
memset(ans, 0, sizeof(ans));
memset(head, -1, sizeof(head));
for(int i=0; i<m; i++)
{
scanf("%d%d%d", &e[i].u, &e[i].v, &e[i].w);
e[i].next = head[e[i].u];
head[e[i].u] = i;
}
printf("%d\n", dijkstra(n));
}
return 0;
}
spfa+stack
#include<iostream>
#include<cstring>
#include<cmath>
#include<cstdio>
#include<algorithm>
#include<stack>
using namespace std;
const int N = 150009;
const int MAX = 0x3f3f3f3f;
bool vis[N];
int d[N];
int ans[N] = {};
int head[N];
struct Edge
{
int u, v, w, next;
}e[N];
int spfa(int n)
{
memset(vis, 0, sizeof(vis));
for(int i=1; i<=n; i++)
d[i] = MAX;
d[1] = 0;
vis[1] = 1;
stack<int> s;
s.push(1);
while(!s.empty())
{
int x = s.top();
s.pop();
vis[x] = 0;
for(int i=head[x]; i!=-1; i=e[i].next)
{
if(d[e[i].v] > d[x] + e[i].w)
{
d[e[i].v] = d[x] + e[i].w;
if(!vis[e[i].v])
{
s.push(e[i].v);
vis[e[i].v] = 1;
}
}
}
}
return d[n];
}
int main()
{
int n, m;
while(~scanf("%d%d", &n, &m))
{
memset(ans, 0, sizeof(ans));
memset(head, -1, sizeof(head));
for(int i=0; i<m; i++)
{
scanf("%d%d%d", &e[i].u, &e[i].v, &e[i].w);
e[i].next = head[e[i].u];
head[e[i].u] = i;
}
printf("%d\n", spfa(n));
}
return 0;
}