UESTC_秋实大哥带我飞 2015 UESTC Training for Graph Theory<Problem B>

B - 秋实大哥带我飞

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

Submit Status

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

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

Input

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

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

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

Output

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

Sample input and output

Sample Input Sample 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;
}
时间: 2024-08-05 07:08:06

UESTC_秋实大哥带我飞 2015 UESTC Training for Graph Theory<Problem B>的相关文章

UESTC_秋实大哥下棋 2015 UESTC Training for Data Structures&lt;Problem I&gt;

I - 秋实大哥下棋 Time Limit: 3000/1000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others) Submit Status 胜负胸中料已明,又从堂上出奇兵.秋实大哥是一个下棋好手,独孤求败的他觉得下棋已经无法满足他了,他开始研究一种新的玩法. 在一个n×m的棋盘上,放置了k个车,并且他在棋盘上标出了q个矩形,表示矩形内部是战略要地. 秋实大哥要求一个矩形内的每一个格子,都至少能被一辆在矩形内的车攻击到,

UESTC_方老师和农场 2015 UESTC Training for Graph Theory&lt;Problem L&gt;

L - 方老师和农场 Time Limit: 3000/1000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others) Submit Status 方老师重新开了一家农场,农场一共有N个节点和M条双向边,但是有一个很大的问题就是有比如一个农场A到达农场B只有一条路径,问至少添加多少条边使得任意两个农场之间的路径多于一条. Input 多组数据,EOF结束. 第1行:N和M. 第2到第M+1行:每一行2个数Ui和Vi,表示Ui到

UESTC_韩爷的情书 2015 UESTC Training for Graph Theory&lt;Problem H&gt;

H - 韩爷的情书 Time Limit: 6000/2000MS (Java/Others)     Memory Limit: 262144/262144KB (Java/Others) Submit Status 某年某月某日,韩爷被妹子表白了\o/ 同时,韩爷收到了来自妹子的情书.在好奇心的驱使下,众人想要一览究竟. 显然,羞涩韩爷是不会把情书直接拿出来的. 假设情书长度为n+2,韩爷从中提取出n个长度为3的连续字符串,分给了n个人. 现在这n个人向你求助,能否帮他们把情书恢复出来. I

UESTC_小panpan学图论 2015 UESTC Training for Graph Theory&lt;Problem J&gt;

J - 小panpan学图论 Time Limit: 3000/1000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others) Submit Status 小panpan不会图论,所以图论专题他非常刻苦地学习图论. 今天他认真地学习了萌神的ppt,学习了一下Floyd算法,手持两把锟斤拷的他, 口中疾呼烫烫烫,马上找了到OJ上找了道FLoyd的题: n个点,m边的无向连通图,无重边,无自环,每条边的长度都是1,求任意两点之间的

UESTC_邱老师的脑残粉 2015 UESTC Training for Graph Theory&lt;Problem D&gt;

D - 邱老师的脑残粉 Time Limit: 12000/4000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others) Submit Status 邱老师的粉丝众多,每天邱老师都得面对粉丝们数不尽的邀约,邱老师一个人处理不过来,所以想请你帮忙. 假设某天有N个粉丝想和邱老师约,一旦某个粉丝成功地约上了邱老师,她就会发微博和朋友炫耀.一旦某个粉丝发现微博里有关于邱老师的消息,她都会转发. 如果当天内某个约上邱老师的粉丝发现微

UESTC_秋实大哥与连锁快餐店 2015 UESTC Training for Graph Theory&lt;Problem A&gt;

A - 秋实大哥与连锁快餐店 Time Limit: 9000/3000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others) Submit Status 成大事者,不惟有超世之才,亦有坚忍不拔之志. 秋实大哥开了一家快餐店之后,由于人赢光环的影响,很快就赚得了大量的资金.为了继续实现心中的远大的理想,他打算在全国各地开设分店赚大钱.假设现在有n家快餐店(其中有至少有一家是旗舰店)分布在二维平面上,第i家快餐店的坐标为(xi,

UESTC_秋实大哥与时空漫游 2015 UESTC Training for Graph Theory&lt;Problem C&gt;

C - 秋实大哥与时空漫游 Time Limit: 4500/1500MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others) Submit Status 秋实大哥通过全国的连锁快餐店发家致富,赚了大钱,接下来他打算通过这些钱实现他的另一个梦想————遨游太空,漫游星际. 秋实大哥满怀期待的出发了. .......啦啦啦啦啦啦啦啦啦...... 最后,秋实大哥花完了钱,觉得是时候回地球继续赚钱和过节了. 但是却被告知回地球的专机

UESTC_排名表 2015 UESTC Training for Graph Theory&lt;Problem I&gt;

I - 排名表 Time Limit: 3000/1000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others) Submit Status 暑假前集训已经过了一半了,我们将会把当前排名公布出来.但是此刻秋实大哥却心急火燎,因为他不慎把排名删除了. 一共有n个人参加排名,每个人都有一个名次,没有哪两个人的名次是相同的.现在秋实大哥掌握的一些情报,比如Ai的名次要先于Bi.(编号从1开始) 你能帮秋实大哥恢复出排名表吗? Inp

UESTC_传输数据 2015 UESTC Training for Graph Theory&lt;Problem F&gt;

F - 传输数据 Time Limit: 3000/1000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others) Submit Status 机房里面有m台电脑,n台网线,每条网线都每秒中最多传送的数据量,现在需要你计算从标号为1的电脑传送数据到编号为m的电脑,问一秒内最多传送多少数据? Input 第1行: 两个用空格分开的整数N(0≤N≤200)和 M(2≤M≤200).N网线的数量,M是电脑的数量. 第二行到第N+1行