P - The Shortest Path in Nya Graph-hdu4725(双端队列+拆点)

题意:有N个点和N层..一层有X个点(0<=X<=N).两邻两层间有一条路花费C。还有M条小路在两个点之间。问从第一个点走到第N个点最短路是多少...

可以考虑在每一层增加一个点,这个点到上下层的距离是C,与本层的距离是0;

T的很惨,不太明白为什么,翻了一下大神的博客,发现这个要把每层拆成两个点来算的,要是只拆成一个点那么本层到本层的点都会是0了

////////////////////////////////////////////////////

时间卡的很恶心,还需要双端队列,如果新加入的点的值比队列顶端的额值小就放在方面,否则就放在下面(不明白优化在那里了.......)

 

 

 

#include<stdio.h>
#include<vector>
#include<stack>
#include<queue>
#include<algorithm>
#include< string.h>
#include<math.h>
using  namespace std;

const  int maxn =  1000005;
const  int maxm =  100005;
const  int oo =  0xfffffff;

struct node
{
     int u, v, c, next;
}e[maxn];
int head[maxm* 3], dis[maxm* 3];
bool use[maxm* 3];

void Add( int u,  int v,  int w,  int k)
{
    e[k].u = u;
    e[k].v = v;
    e[k].c = w;
    e[k].next = head[u];
    head[u] = k;
}
void spfa()
{
    deque< int> Q;
    Q.push_back( 1);

     while(Q.size())
    {
         int i = Q.front();Q.pop_front();
        use[i] =  false;

         for( int j=head[i]; j!= 0; j=e[j].next)
        {
             int u=e[j].u, v=e[j].v, w=e[j].c;

             if(dis[u]+w < dis[v])
            {
                dis[v] = dis[u] + w;

                 if(use[v] ==  false)
                {
                    use[v] =  true;
                     if(Q.size() && dis[v] < dis[Q.front()])
                        Q.push_front(v);
                     else
                        Q.push_back(v);
                }
            }
        }
    }
}

int main()
{
     int T, t= 1;

    scanf( " %d ", &T);

     while(T--)
    {
         int i, N, M, C, u, v, w, x, k= 1;

        scanf( " %d%d%d ", &N, &M, &C);

        memset(head,  0sizeof(head));

         for(i= 1; i<=N; i++)
        {
             // 本层拆出来的点是 出i+N, 入i+2*N

            dis[i] = dis[i+N] = dis[i+ 2*N] = oo;

             if(i != N)
            {
                Add(i+N, i+ 2*N+ 1, C, k++);
                Add(i+N+ 1, i+ 2*N, C, k++);
            }

            scanf( " %d ", &x); // 节点i属于第x层

            Add(i, x+N,  0, k++);
            Add(x+ 2*N, i,  0, k++);
        }

         for(i= 1; i<=M; i++)
        {
            scanf( " %d%d%d ", &u, &v, &w);
            Add(u, v, w, k++);
            Add(v, u, w, k++);
        }

        dis[ 1] =  0;
        spfa();

         if(dis[N] == oo)
            printf( " Case #%d: -1\n ", t++);
         else
            printf( " Case #%d: %d\n ", t++, dis[N]);
    }

     return  0;
}

 

你可能感兴趣的:(Graph)