您的位置:首页 > 其它

poj 3159 Candies

2013-04-30 00:17 387 查看
差束约分

有人将这题归为最短路的中等题,所以做一下,但是发现其实是裸的差束约分

题意:n个人,m个信息,每行的信息是3个数字,A,B,C,表示B比A多出来的糖果不超过C个,问你,n号人最多比1号人多几个糖果

m行信息,所以得到m个不等式 : XB - XA <= C , 所有不等式加起来就是一个差束约分系统

对应最短路模型,一开始是 d[v] >= d[u]+w (有向边u--->v) , 在进行完最短路后则变为 d[v] <= d[u] + w ,转化为 d[v] - d[u] <= w

这个和上面的 XB - XA <= C 是相同的模式 , 因此建图的时候有向边应该是 A----->B , 边权为C

所以我们是要求 max( Xn - X1) , 可知是 Xn - X1 <= res 令其取最大值,就是 Xn - X1 = res

所以以1为源点,n为汇点,运行一次最段落即可

没有负权,所以spfa和dij都可以

另外这题长见识了,用spfa+queue是会超时的,用spfa+stack则500ms。另外写成spfa的dfs搜索式也是会超时的,所以这也验证了spfa很不稳定

同样的,朴素的dij是会超时的,要用堆优化,即优先队列版本的dij

下面只给出spfa+stack(迭代版本,模拟dfs,但是dfs居然超时)的代码

#include <cstdio>
#include <cstring>
#include <stack>
#include <vector>
using namespace std;
#define N 30010
#define M 150010
#define INF 0x3f3f3f3f

int head
;
struct edge
{
int u,v,w,next;
}e[M];
int d
;
int n,tot;
bool ins
;

void add(int u ,int v ,int w)
{
e[tot].u = u; e[tot].v = v; e[tot].w = w;
e[tot].next = head[u]; head[u] = tot++;
}

void spfa(int s, int t)
{
stack<int>sta;
memset(d,0x3f,sizeof(d));
memset(ins,false,sizeof(ins));
while(!sta.empty()) sta.pop();
d[s] = 0;
sta.push(s);
ins[s] = true;
while(!sta.empty())
{
int u,v,w;
u = sta.top();
sta.pop();
ins[u] = false;
for(int k=head[u]; k!=-1; k=e[k].next)
{
v = e[k].v;
w = e[k].w;
if(d[u]+w < d[v])
{
d[v] = d[u] + w;
if(!ins[v])
{
sta.push(v);
ins[v] = true;
}
}
}
}
printf("%d\n",d[t]);
}

int main()
{
int n,m;
scanf("%d%d",&n,&m);
//while(scanf("%d%d",&n,&m)!=EOF)
//{
tot = 0;
memset(head,-1,sizeof(head));
for(int i=0; i<m; i++)
{
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
add(u,v,w);
}
spfa(1,n);
//}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: