一直不知道差分约束是什么类型题目,最近在写最短路问题就顺带看了下,原来就是给出一些形如x-y<=b不等式的约束,问你是否满足有解的问题
好神奇的是这类问题竟然可以转换成图论里的最短路径问题,下面开始详细介绍下
比如给出三个不等式,b-a<=k1,c-b<=k2,c-a<=k3,求出c-a的最大值,我们可以把a,b,c转换成三个点,k1,k2,k3是边上的权,如图
由题我们可以得知,这个有向图中,由题b-a<=k1,c-b<=k2,得出c-a<=k1+k2,因此比较k1+k2和k3的大小,求出最小的就是c-a的最大值了
根据以上的解法,我们可能会猜到求解过程实际就是求从a到c的最短路径,没错的....简单的说就是从a到c沿着某条路径后把所有权值和k求出就是c -a<=k的一个
推广的不等式约束,既然这样,满足题目的肯定是最小的k,也就是从a到c最短距离...
(以上来自博客http://www.cnblogs.com/void/archive/2011/08/26/2153928.html)
去做题了 ,先占个位置 防止自己不做了=,=
POJ 3159
比较裸的一题差分约束 然而用spfa+queue 时间超限了
看了别人的代码,补上比较好的代码
/*-------------------------------------------------------------------
* Purpose:
* POJ 3159 candies 做了一些优化
* Time:
* 2012年3月21日 9:27:16
* Author:
* 张彦升
-------------------------------------------------------------------*/
#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;
const int INF = 0x3f3f3f3f;
const int V = 30001;
const int E = 150001;
int pnt[E],cost[E],nxt[E];
int e,head[V];
int dist[V];
bool vis[V];
int relax(int u,int v,int c)
{
if (dist[v] > dist[u] + c)
{
dist[v] = dist[u] + c;
return 1;
}
return 0;
}
/**
* 读取一个int
*/
inline int read_int()
{
int ret=0;
char tmp;
while(!isdigit(tmp=getchar()));
do{
ret=(ret<<3)+(ret<<1)+tmp-'0';
}while(isdigit(tmp=getchar()));
return ret;
}
void addedge(int u,int v,int c)
{
pnt[e] = v;
cost[e] = c;
nxt[e] = head[u];
head[u] = e++;
}
int SPFA(int src,int n)
{
int i;
for (i = 1;i <= n;i ++)
{
vis[i] = 0;
dist[i] = INF;
}
dist[src] = 0;
int Q[E],top = 1;
Q[0] = src;
vis[src] = true;
while (top)
{
int u,v;
u = Q[--top];
vis[u] = false;
for (i = head[u];i != -1;i = nxt[i])
{
v = pnt[i];
if (1 == relax(u,v,cost[i]) && !vis[v])
{
Q[top++] = v;
vis[v] = true;
}
}
}
return dist[n];
}
int main()
{
int n,m;
while (scanf("%d%d",&n,&m) != EOF)
{
int i,a,b,c;
e = 0;
memset(head,-1,sizeof(head));
for (i = 0;i < m;++i)
{
//cin >> a >> b >> c;
a = read_int();
b = read_int();
c = read_int();
addedge(a,b,c);
}
cout << SPFA(1,n) << endl;
}
return 0;
}
在读入int的时候做了优化,不过个人觉得假如卡scanf读取int的时间的话真是丧尽天良= =