POJ3159---Candies(最短路:spfa+栈or队列)(邻接表)

来源:互联网 发布:仓鼠用品淘宝 编辑:程序博客网 时间:2024/06/17 13:52

【题意来源】: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 0x3f3f3f3fusing 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 0x3f3f3f3fusing 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();}
原创粉丝点击