一道差分约束系统的经典题。
题意:N个人,M个关系式,每个关系式给出ai,bi,ci,使得bi-ai<=ci(ai,bi代表人的编号,ci代表糖果数), 求第N个人在不打破所有关系式的前提下,最多能拿多少糖果。
分析:可以将每个人视作点,每个关系式视作边建图。对不等式bi-ai<=ci,将ai 视作点u,bi 视作点v,则有d[v]<=d[u]+w(u, v)。其形式与最短路算法中的边松弛操作类似。
用优先队列优化的Dijkstra跑出最短路,d[N]就是答案。
#include<iostream> #include<cstring> #include<stdio.h> #include<map> #include<string> #include<algorithm> #include<queue> //#define LOCAL using namespace std; typedef long long LL; const int maxn =3e4+5; const LL INF =(1ll<<60); struct Edge{ int to,next; LL val; }; struct HeapNode{ LL d; //费用或路径 int u; bool operator < (const HeapNode & rhs) const{return d > rhs.d;} }; struct Dijstra{ int n,m,tot; Edge edges[maxn<<4]; bool used[maxn]; LL d[maxn]; int head[maxn]; void init(int n){ this->n = n; this->tot=0; memset(head,-1,sizeof(head)); } void Addedge(int u,int v ,LL dist){ edges[tot].to = v; edges[tot].val = dist; edges[tot].next = head[u]; head[u] = tot++; } void dijkstra(int s){ memset(used,0,sizeof(used)); priority_queue<HeapNode> Q; for(int i=0;i<=n;++i) d[i]=INF; d[s]=0; Q.push((HeapNode){0,s}); while(!Q.empty()){ HeapNode x =Q.top();Q.pop(); int u =x.u; if(used[u]) continue; used[u]= true; for(int i=head[u];~i;i=edges[i].next){ Edge & e = edges[i]; if(d[e.to] > d[u] + e.val){ d[e.to] = d[u] +e.val; Q.push((HeapNode){d[e.to],e.to}); } } } } }G; int main() { #ifdef LOCAL freopen("in.txt","r",stdin); freopen("out.txt","w",stdout); #endif int N,M,u,v; LL tmp; while(scanf("%d%d",&N,&M)==2){ G.init(N); for(int i=1;i<=M;++i){ scanf("%d%d%I64d",&u,&v,&tmp); G.Addedge(u,v,tmp); //有向边 } G.dijkstra(1); LL res=G.d[N]; printf("%I64d ",res); } return 0; }