http://poj.org/problem?id=3159 (題目鏈接)
題意:有n個小朋友,班長要給每個小朋友發糖果。m種限制條件,小朋友A不允許小朋友B比自己多C個糖果。問第1個小朋友最多比第n個小朋友多多少糖果。
Solution
原來這就是所謂的差分約束。。淺顯易懂的博客,超詳細的博客。
總結一下:
>=,求最小值,做最長路;
<=,求最大值,做最短路。
可能會覺得很奇怪,用線性規劃的角度解釋吧。其實我們需要求的就是(n)-(1)<=x或者(n)-(1)>=x,要保證滿足所有的約束的話,我們需要求出最小(大)的x。所以就用最短路求出<=情況的最小x,用最長路求出>=情況的最大x。
還有就是有最短路負環(最長路正環)的話說明無解。答案爲inf(-inf)時爲任意解。
代碼:
// poj3159
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<queue>
#define LL long long
#define inf 2147483640
#define MOD 998244353
#define Pi acos(-1.0)
#define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
using namespace std;
inline LL getint() {
int f,x=0;char ch=getchar();
while (ch<='0' || ch>'9') {if (ch=='-') f=-1;else f=1;ch=getchar();}
while (ch>='0' && ch<='9') {x=x*10+ch-'0';ch=getchar();}
return x*f;
}
const int maxn=30010,maxm=150010;
struct edge {int to,next,w;}e[maxm];
struct data {
int x,num;
friend bool operator < (const data &a,const data &b) {
return a.x>b.x;
}
};
int dis[maxn],vis[maxn],head[maxn],cnt,n,m;
priority_queue<data> q;
void insert(int u,int v,int w) {
e[++cnt].to=v;e[cnt].next=head[u];head[u]=cnt;e[cnt].w=w;
}
void Dijistra() {
data x,y;
x.x=0;x.num=1;
for (int i=1;i<=n;i++) dis[i]=inf;
dis[1]=0;
q.push(x);
while (q.size()) {
x=q.top();q.pop();
if (vis[x.num]) continue;
vis[x.num]=1;
for (int i=head[x.num];i;i=e[i].next)
if (e[i].w+x.x<dis[e[i].to] && !vis[e[i].to]) {
y.num=e[i].to;
dis[e[i].to]=y.x=e[i].w+x.x;
q.push(y);
}
}
}
int main() {
scanf("%d%d",&n,&m);
for (int u,v,w,i=1;i<=m;i++) {
scanf("%d%d%d",&u,&v,&w);
insert(u,v,w);
}
Dijistra();
printf("%d",dis[n]);
return 0;
}