差分约束
POJ 3159
差分约束问题的最基础例题
题目大意:N个人,M个信息,每个信息A,B,C表示B的糖果最多比A多C个,求第N个人最多比第一个人多多少个糖果。
分析:最短路模型松弛后的路径 d[v]<=d[u]+w ,即d[v]-d[u]<=w,w表示从u到v的权值,而上述的题意可转化为B-A<=C,即C是从A到B的边。那么原题目就是给你M个边,让你去得到1—N最短路径便是最大值,那么问题就来了,为什么不是求最长路径,不是说要我们求最多的糖果差值吗?
我们拿一个简单的例子来讲:
转化为式子就是:
- d[3]<=d[1]+4;
- d[2]<=d[1]+5;
- d[3]<=d[2]-2;
化简一下得:d[3]<=d[2]-2<=d[1]+3;
现在得到把这个式子和1式合并
1.d[3]<=d[1]+4;
2.d[3]<=d[1]+3;
为保证同时满足,只能取2式,推广到1—n的话也就是要求1—n的最短路径
那么问题解决了之后,就要考虑一下手段了,我用kuangbin的dijkstra+优先队列模板超时了,用SPFA+队列也超时了。看了一下大神操作,用了数组实现邻接表的方法过了
下面是代码
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<vector>
#include<stack>
#include<bitset>
#include<cstdlib>
#include<cmath>
#include<set>
#include<list>
#include<deque>
#include<queue>
#define ll long long
#define pb push_back
using namespace std;
const int INF=0x3f3f3f3f;
const int maxn=30090;
struct qnode
{
int v;
int c;
qnode(int _v=0,int _c=0):v(_v),c(_c) {}
bool operator <(const qnode &r)const
{
return c>r.c;
}
};
struct Edge
{
int v,cost,next;
}edge[5*maxn];
bool vis[maxn];
int d[maxn];
int head[maxn];
int tol;
void dijkstra(int n,int sx)
{
memset(vis,false,sizeof vis);
fill(d+1,d+1+n,INF);
priority_queue<qnode> q;
while(!q.empty())q.pop();
d[sx]=0;
q.push(qnode(sx,0));
qnode tmp;
while(!q.empty())
{
tmp=q.top();
q.pop();
int u=tmp.v;
if (vis[u])continue;
vis[u]=true;
for (int i=head[u]; i!=-1; i=edge[i].next)
{
int v=edge[i].v;
int cost=edge[i].cost;
if (!vis[v]&&d[v]>d[u]+cost)
{
d[v]=d[u]+cost;
q.push(qnode(v,d[v]));
}
}
}
}
void add(int u,int v,int w)
{
edge[tol].v=v;
edge[tol].cost=w;
edge[tol].next=head[u];
head[u]=tol++;
}
int main()
{
int n,m,a,b,c,tol=0;
scanf("%d%d",&n,&m);
memset(head,-1,sizeof head);
for (int i=0; i<m; i++)
{
scanf("%d%d%d",&a,&b,&c);
add(a,b,c);
}
dijkstra(n,1);
cout<<d[n]<<endl;
return 0;
}
数组实现邻接表具体原理也没搞懂,链表这东西看着太烦躁了,姑且打打板子吧呜呜呜