最短路计数

链接:

这是个真的签到题...

经过一个寒暑假的洗礼

相信你们对图论,提升了很大的兴趣

那么这题我直接就扔给你作为一个签到题

好了,你只需要找一个最短路有几条即可。

不会吧不会吧,不会真有人觉得是最短路计数叭

CCoolGuang当然要给你们上条件的

给出一个起点SS,一个终点TT,你要求出从STS→T是最短路的情况下,最大边权不超过WW的路径有多少条

答案对1e9+71e9+7取余

Input

第一行:n,m,S,T,Wn,m,S,T,W

接下来mm行分别为:x,y,wx,y,w,代表xyww是一条边权为ww的有向边

Output

按照题目输出

Samples

Input Copy
4 5 1 4 2
1 2 3
2 4 1
3 2 2
1 3 1
3 4 3
Output
1

Hint

n50000n≤50000,m100000m≤100000

对于第一个样例的解释:

#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
#include<cstring>
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<bits/stdc++.h> 
using namespace std;
typedef long long ll;
template <typename Tp>
void read(Tp &x){//read(n);
    x=0;char ch=1;int fh;
    while(ch!='-'&&(ch>'9'||ch<'0')){
        ch=getchar();
    }
    if(ch=='-'){
        fh=-1;ch=getchar();
    }else fh=1;
    while(ch>='0'&&ch<='9'){
        x=(x<<1)+(x<<3)+ch-'0';ch=getchar();
    }
    x*=fh;
}
inline char read1()//字符串读入挂
{
    register char ch=getchar();
    while(ch<'A'||ch>'M')ch=getchar();
    return ch; 
}
const int maxn=1e6+100;
int head[maxn],d[maxn],ans[maxn];
int vis[maxn];
int n,m,s,t,W;
struct node{
    int to;
    int next;
    int w;
}edge[maxn];
int cnt=0;
void add(int u,int v,int w){
    edge[++cnt].w=w;
    edge[cnt].to=v;
    edge[cnt].next=head[u];
    head[u]=cnt;
}
void spfa(){
    memset(d,0x3f3f3f,sizeof d);
    queue<int>q;
    d[s]=0;//起点 
    vis[s]=1;
    ans[s]=1;// 本身为1个最短路 
    q.push(s);
    while(q.size()){
        int x=q.front();q.pop();
        vis[x]=0;
        for(int i=head[x];i;i=edge[i].next){
            int y=edge[i].to;
            if(d[y]>d[x]+edge[i].w){//如果满足u到v的距离比原本到v的距离小,则更新
                d[y]=d[x]+edge[i].w;
                ans[y]=ans[x];// x点和y点在一条路上,所以y的最短路个数等于x的最短路个数
                if(!vis[y]){
                    q.push(y);
                    vis[y]=1;
                }
            }
            else if(d[y]==d[x]+edge[i].w){
                ans[y]+=ans[x];// 该点最短路个数为y最短路个数+x最短路个数
//                ans[y]%=mod;
            }
        } 
    }
    
}
int main(){
    cin>>n>>m>>s>>t>>W;
    ll a,b,z;
    for(int i=1;i<=m;i++){
        read(a),read(b),read(z);
        if(z>W){
            continue;
        }
        add(a,b,z);
    }
    spfa();
    cout<<ans[t]<<endl;
    
} 

例二:

洛谷:P1144 最短路计数 

题目描述

给出一个NN个顶点MM条边的无向无权图,顶点编号为1-N1N。问从顶点11开始,到其他每个点的最短路有几条。

输入格式

第一行包含22个正整数N,MN,M,为图的顶点数与边数。

接下来MM行,每行22个正整数x,yx,y,表示有一条顶点xx连向顶点yy的边,请注意可能有自环与重边。

输出格式

NN行,每行一个非负整数,第ii行输出从顶点11到顶点ii有多少条不同的最短路,由于答案有可能会很大,你只需要输出ans \bmod 100003ansmod100003后的结果即可。如果无法到达顶点ii则输出00。

输入输出样例

输入 #1
5 7
1 2
1 3
2 4
3 4
2 3
4 5
4 5
输出 #1
1
1
1
2
4

说明/提示

11到55的最短路有44条,分别为22条1-2-4-51245和22条1-3-4-51345(由于4-545的边有22条)。

对于20\%20%的数据,N ≤ 100N100;

对于60\%60%的数据,N ≤ 1000N1000;

对于100\%100%的数据,N<=1000000,M<=2000000N<=1000000,M<=2000000。

//#pragma GCC optimize(1)
//#pragma GCC optimize(2)
//#pragma GCC optimize(3,"Ofast","inline")
#include<cstring>
#include<cstdio>
#include<iostream>
#include<queue> 
#include<algorithm>
using namespace std;
typedef long long ll;
template <typename Tp>
void read(Tp &x){//read(n);
    x=0;char ch=1;int fh;
    while(ch!='-'&&(ch>'9'||ch<'0')){
        ch=getchar();
    }
    if(ch=='-'){
        fh=-1;ch=getchar();
    }else fh=1;
    while(ch>='0'&&ch<='9'){
        x=(x<<1)+(x<<3)+ch-'0';ch=getchar();
    }
    x*=fh;
}
inline char read1()//字符串读入挂
{
    register char ch=getchar();
    while(ch<'A'||ch>'M')ch=getchar();
    return ch; 
}
const int maxn=1e6+100;
const int mod=100003; 
int head[maxn],d[maxn],ans[maxn];
int vis[maxn];
int n,m,s,t,W;
struct node{
    int to;
    int next;
    int w;
}edge[maxn];
int cnt=0;
void add(int u,int v,int w){
    edge[++cnt].w=w;
    edge[cnt].to=v;
    edge[cnt].next=head[u];
    head[u]=cnt;
}
void spfa(){
    memset(d,0x3f3f3f,sizeof d);
    queue<int>q;
    d[s]=0;//起点 
    vis[s]=1;
    ans[s]=1;// 本身为1个最短路 
    q.push(s);
    while(q.size()){
        int x=q.front();q.pop();
        vis[x]=0;
        for(int i=head[x];i;i=edge[i].next){
            int y=edge[i].to;
            if(d[y]>d[x]+edge[i].w){//如果满足u到v的距离比原本到v的距离小,则更新
                d[y]=d[x]+edge[i].w;
                ans[y]=ans[x];// x点和y点在一条路上,所以y的最短路个数等于x的最短路个数
                if(!vis[y]){
                    q.push(y);
                    vis[y]=1;
                }
            }
            else if(d[y]==d[x]+edge[i].w){
                ans[y]+=ans[x];// 该点最短路个数为y最短路个数+x最短路个数
                ans[y]%=mod;
            }
        } 
    }
    
}
int main(){
    cin>>n>>m;
    s=1;//起点 
    for(int i=1;i<=m;i++){
        int a,b;
        read(a),read(b);
        add(a,b,1);
        add(b,a,1);
    }
    spfa();
    for(int i=1;i<=n;i++){
        cout<<ans[i]<<endl;
    } 
    
} 

 

posted @ 2020-09-28 20:42  哎呦哎(iui)  阅读(148)  评论(0编辑  收藏  举报