标签:
然而题目和题面并没有什么关系。
给出n个点,m条带权无向边,问你从1号点到n号点的最短路中有多少种走法?
第一行两个数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号点,点和边都可以被走多次。
如果有无穷种走法,输出-1
。否则输出走法的方案数mod 1000000009
。
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 边的话,那么肯定是有无穷多种走法的.
那么我们就设到达终点的状态有两种:
这样,我们第一遍先跑一次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; }
UESTC_秋实大哥带我飞 2015 UESTC Training for Graph Theory<Problem B>
标签:
原文地址:http://www.cnblogs.com/Xiper/p/4570647.html