【题意来源】:http://poj.org/problem?id=3159
【题意】
班长分糖,规定是,B童鞋分的糖不能超过A童鞋C个(输入数据:A B C),那么,假设共有n个同学,编号1~n,那么n好同学最多比1号同学多多少个?
【思路】
不等式问题,可由差分约束系统转变为最短路问题。(差分约束现在还不大懂。。)
大致说一下我的思考过程:
假设S数组代表最优情况下每个人得到的糖的数量,那么由题意可得:
S(B)-S(A)<=C,转化为:S(B)<=S(A)+C。
那么,就可以转变为最短路问题,也即是:
if(S(B)>S(A)+C) S(B)=S(A)+C。求出最短路。
但是有的人会疑问:不是让求max(S(n)-S(1)),这样下去只会得到min(S(n)-S(1))。这个问题我也不大懂。先给出链接:浅析差分约束系统,但是按照我上面推导是大于还是小于是没有错的。。。
还有一点要说明:这道题非常卡数据、卡时间。
数据问题呢,我用双向队列试了出来,最短路的spfa算法呢,每从队列里拿出一个点(被更新过的,要么就是起点),用于更新其他点,那么假设当前取出一个点去更新完一个点后,被更新的点将何去何从?
分析:
优先队列:会被丢进队列,然后自动排序,队首依旧是最小的那个。
普通队列:会被丢进队尾,需要前面的被取出完才能被取出。
栈:会被丢进队首,当前点更新所有点之后,会被取出。
这道题,绝大部分用栈(又名堆栈)过的这道题,那么栈和队列有什么区别呢?
相同的时间复杂度下,队列是队尾进,队首出,而栈是队首进,队首出。
而优先队列就是优化了一部分多余的查找过程,队首就直接是最小的(但是可能由于卡时间,所以普通的优先队列过不了),那么,为什么队列会TLE,而栈没有呢。。。我想到的唯一原因是。。数据问题,更新的点刚好是最小的点,然后放在队首。。。
【代码1】
516ms
#include<cmath>
#include<cstdio>
#include<queue>
#include<vector>
#include<cstring>
#include<algorithm>
#define INF 0x3f3f3f3f
using namespace std;
int n,m,tot;
struct pp
{
int v,w;
int nexx;
}edge[150000+10];
int vis[30000+10],d[30000+10],first[30000+10];
int spot[30000+10];
void spfa()
{
memset(vis,0,sizeof(vis));
for(int i=2;i<=n;i++)
d[i]=INF;
d[1]=0;
int top=1;
spot[1]=1;
vis[1]=1;
while(top!=0)
{
int res=spot[top--];
vis[res]=0;
for(int i=first[res];i!=-1;i=edge[i].nexx)
{
if(d[edge[i].v]>d[res]+edge[i].w)
{
d[edge[i].v]=d[res]+edge[i].w;
if(!vis[edge[i].v])
{
spot[++top]=edge[i].v;
vis[edge[i].v]=1;
}
}
}
}
printf("%d\n",d[n]);
}
int main()
{
scanf("%d%d",&n,&m);
tot=0;
for(int i=1;i<=n;i++)
first[i]=-1;
while(m--)
{
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
edge[tot].nexx=first[u];
edge[tot].v=v;
edge[tot].w=w;
first[u]=tot++;
}
spfa();
}
【代码2】
deque(双向队列)实现的栈的功能(实现的队列依旧会TLE)657ms
#include<cmath>
#include<cstdio>
#include<queue>
#include<vector>
#include<cstring>
#include<algorithm>
#define INF 0x3f3f3f3f
using namespace std;
int n,m,tot;
struct pp
{
int v,w;
int nexx;
}edge[150000+10];
int vis[30000+10],d[30000+10],first[30000+10];
int spot[30000+10];
void spfa()
{
memset(vis,0,sizeof(vis));
for(int i=2;i<=n;i++)
d[i]=INF;
d[1]=0;
deque<int> q;
vis[1]=1;
q.push_back(1);
while(!q.empty())
{
int res=q.front();
q.pop_front();
vis[res]=0;
for(int i=first[res];i!=-1;i=edge[i].nexx)
{
if(d[edge[i].v]>d[res]+edge[i].w)
{
d[edge[i].v]=d[res]+edge[i].w;
if(!vis[edge[i].v])
{
// if(!q.empty()&&d[edge[i].v]<d[q.front()])
q.push_front(edge[i].v);
// else
// q.push_back(edge[i].v);
vis[edge[i].v]=1;
}
}
}
}
printf("%d\n",d[n]);
}
int main()
{
scanf("%d%d",&n,&m);
tot=0;
for(int i=1;i<=n;i++)
first[i]=-1;
while(m--)
{
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
edge[tot].nexx=first[u];
edge[tot].v=v;
edge[tot].w=w;
first[u]=tot++;
}
spfa();
}