hdu4725 The Shortest Path in Nya Graph

题意:n个点,给定每个点的层次,可以从当前层任何节点到达下一个层任何节点,x->x+1 ,x+1->x 花费c,还有一些额外的边可以直接走。求1-n的最短路

做法:想到了如果直接扩展所有节点的话肯定超时,所以找出关键点扩展就好了,什么关键点,叫着好听而已,就是那些必要的点而已,包括给出的边的点,还有起点终点,每层至少保证一个点。然后spfa迭代,按额外的边迭代,往上一层迭代,往下一层迭代。

刚开始没能保证n点加进去,一直wa

#define maxn 100005

const int inf = 0x3fffffff;

struct node
{
  int v,next;
  int w ;
};
node e[maxn * 2 ];
int cnt ;
int head[maxn];
vector<int> p[maxn],p1[maxn];
int vis[maxn];
int lev[maxn];
int n,m,c;
int _mx;
int dis[maxn];
void init()
{
  memset(head,-1,sizeof(head));
  cnt = 0 ;
}
void add(int u , int v , int w )
{
  //printf("add %d %d %d \n",u,v,w);
  e[cnt].v = v ;
  e[cnt].w = w ;
  e[cnt].next = head[u] ;
  head[u] = cnt ++ ;
  e[cnt].v = u;
  e[cnt].w = w;
  e[cnt].next = head[v];
  head[v] = cnt ++ ;
  return ;
}
queue<int> q;
void spfa()
{
  while(!q.empty()) q.pop();
  for(int i = 0; i <= n ; i ++ )
  {
    vis[i] = 0 ;
    dis[i] = inf;
  }
  vis[1] = 1 ;
  dis[1] = 0 ;
  q.push(1);
  int u , v , ll ,sz ;
  while(!q.empty())
  {
    u = q.front();
   // printf("u = %d lev[%d] = %d\n",u,u,lev[u]);
   // printf("dis[u] = %d\n",dis[u]);
    q.pop();
    for(int i = head[u]; i != -1 ; i = e[i].next)
    {
      //printf("e[i].w = %d\n",e[i].w);
      v = e[i].v;
      if(dis[u] + e[i].w < dis[v] )
      {
        dis[v] = dis[u] + e[i].w ;
       // printf("dis[%d] = %d\n",v,dis[v]);
        if(!vis[v] )
        {
          vis[v] = 1 ;
          q.push(v);
        }
      }
    }
    ll = lev[u];
    if(ll != 1 )
    {
      sz = p1[ll-1].size();
      for(int i = 0 ; i < sz; i ++ )
      {
        v = p1[ll-1][i];
        if(dis[u] + c < dis[v] )
        {
          dis[v] = dis[u] + c ;
          if(!vis[v] )
          {
            vis[v] = 1 ;
            q.push(v);
          }
        }
      }
    }
    if(ll != _mx)
    {
      sz = p1[ll+1].size();
      for(int i = 0 ; i < sz; i ++ )
      {
        v = p1[ll+1][i];
        if(dis[u] + c < dis[v] )
        {
          dis[v] = dis[u] + c ;
         // printf("dis[%d] = %d\n",v,dis[v]);
          if(!vis[v] )
          {
            vis[v] = 1 ;
            q.push(v);
          }
        }
      }
    }
    vis[u] = 0;
  }

}

int main()
{
  int cas;
  int cast = 0 ;
  scanf("%d",&cas);
  while(cas -- )
  {
    scanf("%d%d%d",&n,&m,&c);
   // printf("c = %d\n",c);
    memset(lev, 0 , sizeof(lev));
    for(int i = 1 ; i <= n; i ++ ) p[i].clear(),p1[i].clear();
    memset(vis,0,sizeof(vis));
    _mx = 0 ;
    for(int i = 1 ; i <= n ; i++ )
    {
      scanf("%d",&lev[i]);
      _mx = max(_mx , lev[i]);
      p[lev[i]].push_back(i);
      if(p1[lev[i]].size() <= 3 )
      {
        p1[lev[i]].push_back(i);
        vis[i] = 1 ;
      }
    }
    init();
    int u,v,w;
    for(int i = 0; i < m ; i ++ )
    {
      scanf("%d%d%d",&u,&v,&w);
      add(u,v,w);
      if(!vis[u])
      {
        p1[lev[u]].push_back(u);
        vis[u] = 1 ;
      }
      if(!vis[v] )
      {
        p1[lev[v]].push_back(v);
        vis[v] = 1 ;
      }
    }
    if(n == 0 )
    {
      printf("Case #%d: -1\n",++cast);
      continue;
    }
    else if(n == 1 )
    {
      printf("Case #%d: 0\n",++cast);
      continue;
    }
    if(!vis[1])p1[lev[1]].push_back(1);
    if(!vis[n])p1[lev[n]].push_back(n);
   // for(int i = 1 ; i <= _mx; i ++ )
    //{
    //  for(int j = 0 ; j < p1[i].size(); j ++ )
   //   {
    //    printf("%d ",p1[i][j]);
    //  }
   //   printf("\n");
   // }
    spfa();
    printf("Case #%d: ",++cast);
    if(dis[n] >= inf)
      printf("-1\n");
    else printf("%d\n",dis[n]);
  }
  return 0;
}
View Code

 

posted on 2013-09-11 20:37  oshixiaoxiliu  阅读(245)  评论(0编辑  收藏  举报

导航