poj 3159 Candies
这题目做的一个纠结啊。
N个人份糖果,其中含有约束条件,即对于a,b,c有 b-a<=c,看到这个不等式马上感觉到要用最短路解决了,问Sn-S1的最大值是多少,我们令S1=0即求Sn的最大值,查分约束题目,
求最短路,初始原点1到2,3,..,n的距离为INF,每次松弛找到第一组满足约束条件的解,这个解就是最大值,但是这个题目有问题啊,用最常用的bellman_ford无法通过啊,n,m值太大了,只能用spfa或者其他的优化方法,这个题用spfa+stack,用queue也会超时的,我猜想可能stack的访问效率较后者快吧,我最开始用的dijkstra+优先队列,不是超时就是WA,WA的时候我真搞不明白为什么,感觉很简单的题目怎么回WA呢,郁闷死了。。下面附上spfa+stack的代码吧。刚明白为什么我刚才用di。。为何错误了,由于一个节点可以多次如队列,这样由于入队列的仅仅是一个简单的int,无法区分,我们只需定义一个结构体包含节点号及当前len即可,两种方法都a了,。。
#include <iostream>
#include <queue>
#include <stack>
#include <stdio.h>
using namespace std;
const int N=150002;
const int INF=10000000;
struct node{
int to,next,weight;
};
node edge[N];
int num,n,m,dist[30002],adj[30002];
struct cmp
{
bool operator() (const int &a, const int &b)
{
return dist[a] > dist[b];
}
};
void dijkstra(int s)
{
int u,i,v,w;
bool visit[30002];
for(i=0;i<=n;i++)
{
dist[i]=INF;
visit[i]=false;
}
dist[s]=0;
int Stack[30002],top=0;
Stack[top++]=s;
visit[s]=true;
while(top)
{
u=Stack[--top];
visit[u]=false;
for(i=adj[u];i!=-1;i=edge[i].next)
{
// cout<<dist[u]<<" "<<edge[i].weight<<" "<<dist[edge[i].to]<<endl;
v=edge[i].to;
w=edge[i].weight;
if(dist[v]>dist[u]+w)
{
dist[v]=dist[u]+w;
if(!visit[v])
{
Stack[top++]=v;
visit[v]=true;
}
}
}
}
printf("%d\n",dist[n]);
}
int main()
{
scanf("%d%d",&n,&m);
int i,a,b,w;
num=0;
for(i=0;i<=n;i++)
adj[i]=-1;
for(i=0;i<m;i++)
{
scanf("%d%d%d",&a,&b,&w);
edge[num].to=b;
edge[num].weight=w;
edge[num].next=adj[a];
adj[a]=num++;
}
dijkstra(1);
return 0;
}
下面的是dijkstra+优先队列,只贴核心:
priority_queue<qNode> q;
qNode tmp,newNode;
tmp.x=s;
tmp.d=0;
q.push(tmp);
while(!q.empty())
{
tmp=q.top();q.pop();
u=tmp.x;
if(visit[u])
continue;
visit[u]=true;
if(u == n)
break;
for(i=adj[u];i!=-1;i=edge[i].next)
{
// cout<<dist[u]<<" "<<edge[i].weight<<" "<<dist[edge[i].to]<<endl;
v=edge[i].to;
w=edge[i].weight;
if(!visit[v] && dist[v]>dist[u]+w)
{
dist[v]=dist[u]+w;
newNode.x=v;
newNode.d=dist[v];
q.push(newNode);
}
}
}