B - 秋实大哥带我飞

Time Limit: 300/100MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others)
 

Qiushidage Bring Me Fly

然而题目和题面并没有什么关系。

给出n个点,m条带权无向边,问你从1号点到n号点的最短路中有多少种走法?

Input

第一行两个数n,m分别表示点的个数和边的个数。 (2n20001m2000

接下来m行,每行3个数u,v,w表示u号点到v号点有一条距离为w的边。(1u,vn0w100000

数据保证1号点能够到达n号点,点和边都可以被走多次。

Output

如果有无穷种走法,输出-1。否则输出走法的方案数mod 1000000009

Sample input and output

Sample InputSample Output
4 4
1 2 1
1 3 1
2 4 1
3 4 1
2
4 4
1 2 1
1 3 1
2 4 1
3 4 0
-1

 

解题思路:

首先我们可以很容易得出:如果通往终点的最短路径上存在 0 边的话,那么肯定是有无穷多种走法的.

 那么我们就设到达终点的状态有两种:

  1. 在通往终点的路上经过 过 0 边
  2. 在通往终点的路上没有经过 过 0 边.

这样,我们第一遍先跑一次spfa,得出两种状态的最小时间分别为t1,t2.

如果t2 < t1 ,那么路径肯定是有限条的,我们这时候再跑一次dijkstra求最短路数量即可.

那么如果t2 >= t1呢,那么最短路径上肯定存在 0 边,即显然有无穷种走法.

 

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <queue>
#include <vector>
#include <set>
#define pb push_back
using namespace std;
typedef long long ll;
const int maxn = 2e3 + 50;
const int mod = 1000000009;
const int inf = 1 << 29;
typedef struct Edge
{
 int v,w;
 Edge(int v,int w)
  {
       this->v = v ,this->w = w;
  }    
};

vector<Edge>E[maxn];

int n,m,ans = 1,mincost[maxn][2];
bool inqueue[maxn][2];


typedef struct updatastatus
{
  int pos;
  int passzero;
  updatastatus(int pos,int passzero)
   {
      this->pos = pos , this->passzero = passzero ;
   }    
};

queue<updatastatus>q;

void spfa()
{
   q.push(updatastatus(1,0));
   mincost[1][0] = 0;
   mincost[1][1] = 1 << 28;
   while(!q.empty())
    {
       int pos = q.front().pos , zero = q.front().passzero;q.pop();
       for(int i = 0 ; i < E[pos].size() ; ++ i)
        {
            int nextnode = E[pos][i].v;
            int newcost = mincost[pos][zero] + E[pos][i].w;
            if (zero || !E[pos][i].w)
             {
                 if (mincost[nextnode][1] == -1 || mincost[nextnode][1] > newcost)
                  {
                      mincost[nextnode][1] = newcost;
                      if (!inqueue[nextnode][1])
                       {
                         q.push(updatastatus(nextnode,1));
                         inqueue[nextnode][1] = false;
                     }
                 }
             }
            else
             {
                 if (mincost[nextnode][0] == -1 || mincost[nextnode][0] > newcost)
                   {
                     mincost[nextnode][0] = newcost;
                    if (!inqueue[nextnode][0])
                       {
                         q.push(updatastatus(nextnode,0));
                         inqueue[nextnode][0] = false;
                     }
                  }
             }
        }
    }
}

typedef struct tnode
{
  int u,d;
  friend bool operator < (const tnode & x,const tnode & y)
   {
      return x.d > y.d;    
   }    
  tnode(int u,int d)
   {
         this->u = u , this->d = d;
   }
};

int times[maxn];
priority_queue<tnode>dq;

void dijkstra()
{
   bool vis[maxn];
   int  dis[maxn];
   memset(vis,false,sizeof(vis));
   for(int i = 1 ; i <= n ; ++ i) dis[i] = inf;
   dis[1] = 0;
   times[1] = 1;
   dq.push(tnode(1,0));
   while(!dq.empty())
    {
       int u = dq.top().u , d = dq.top().d;dq.pop();
       if (vis[u]) continue;
       vis[u] = true;
       for(int i = 0 ; i < E[u].size() ; ++ i)
        {
            int nextnode = E[u][i].v;
            int newcost = E[u][i].w;
            if (dis[nextnode] > dis[u] + newcost)
             {
                 dis[nextnode] = dis[u] + newcost;
                 times[nextnode] = times[u];
                 times[nextnode] %= mod;
                 dq.push(tnode(nextnode,dis[nextnode]));
             }
            else if(dis[nextnode] == dis[u] + newcost)
             {
                 times[nextnode] = (times[nextnode] + times[u]) % mod;
             }
        }
    }
}


int main(int argc,char *argv[])
{
  scanf("%d%d",&n,&m);
  for(int i = 0 ; i < m ; ++ i)
   {
         int u,v,w;
         scanf("%d%d%d",&u,&v,&w);
         E[u].pb(Edge(v,w));
         E[v].pb(Edge(u,w));
   }
  memset(mincost,-1,sizeof(mincost));
  memset(inqueue,false,sizeof(inqueue));
  memset(times,0,sizeof(times));
  spfa();
  if (mincost[n][1] <= mincost[n][0] && mincost[n][1] != -1)
   printf("-1\n");
  else if (mincost[n][0] != -1)
   {
        dijkstra();
        printf("%d\n",times[n] % mod);
   }
  else
   printf("-1\n");
  return 0;
}

 

posted on 2015-06-12 00:54  天心散人  阅读(363)  评论(0编辑  收藏  举报