1. 程式人生 > >POJ 3159 Candies 還是差分約束(棧的SPFA)

POJ 3159 Candies 還是差分約束(棧的SPFA)

題目大意:

n個小朋友分糖果,你要滿足他們的要求(a b x 意思為b不能超過a x個糖果)並且編號1和n的糖果差距要最大。

思路:

嗯,我先揭發一下,1號是分糖果的孩子,班長大人!(公報私仇啊。。。,欺負N號的小朋友~ 好吧,我開玩笑的)

嗯,這題要求最短路徑。為啥是最短?你以前都在玩最長呀~

因為這題要求的是最大的。圖的三角不等式有:d[v]- d[u]<=w(u,v);  d[v]<=d[u]+w(u,v); 即而鬆弛的條件為: if(d[v]>d[u]+w(u,v))   d[v]=d[u]+w(u,v); 通過不斷的鬆弛,使得d的值不斷變小,直到滿足所有條件,也就是說滿足條件的時候就是最大的了~

建立圖,b - a <=x 然後就是spfa了,不過這題竟然卡隊列了。。看discuss人家用stack,然後我也改了,就這樣過了。。。。。。

還有這題不能建立超級源點。

設第i個小孩子分到的糖果為s[i],那麼 有s[i]>=0

而上面的是b-a<=x,由於這題求的是最短路徑,所以要改為小於號也就是   -s[i]<=0,然後如果新增一個點比如說0那麼就是應該從i到0了,那麼就無用了。。。。

#include<cstdio>
#include<cstring>
#include<stack>
using namespace std;
const int MAXN=30000+10;
const int MAXM=350000;
const int INF=-999999;
int n,m,head[MAXN],len,dis[MAXN];
bool vis[MAXN];

struct edge
{
	int to,val,next;
}e[MAXM];
void add(int from,int to,int val)
{
	e[len].to=to;
	e[len].val=val;
	e[len].next=head[from];
	head[from]=len++;
}
void spfa()
{
	int s=1;
	stack<int> q;
	q.push(s);
	vis[s]=true;
	dis[s]=0;
	while(!q.empty())
	{
		int cur=q.top();
		q.pop();
		vis[cur]=false;
		for(int i=head[cur];i!=-1;i=e[i].next)
		{
			int id=e[i].to;
			if(dis[id] > dis[cur] + e[i].val)
			{
				dis[id]=dis[cur]+e[i].val;
				if(!vis[id])
				{
					q.push(id);
					vis[id]=true;
				}
			}
		}
	}
}
int main()
{
	while(~scanf("%d%d",&n,&m))
	{
		for(int i=1;i<=n;i++)
		{
			head[i]=-1;
			dis[i]=-INF;
			vis[i]=false;
		}
		len=0;

		for(int i=0;i<m;i++)
		{
			int from,to,val;
			scanf("%d%d%d",&from,&to,&val);
			add(from,to,val);
		}

		spfa();
		printf("%d\n",dis[n]);
	}
	return 0;
}