这是个真的签到题...
经过一个寒暑假的洗礼
相信你们对图论,提升了很大的兴趣
那么这题我直接就扔给你作为一个签到题
好了,你只需要找一个最短路有几条即可。
不会吧不会吧,不会真有人觉得是最短路计数叭
CCoolGuang当然要给你们上条件的
给出一个起点SS,一个终点TT,你要求出从S→TS→T是最短路的情况下,最大边权不超过WW的路径有多少条
答案对1e9+71e9+7取余
Input
第一行:n,m,S,T,Wn,m,S,T,W
接下来mm行分别为:x,y,wx,y,w,代表xx yy ww是一条边权为ww的有向边
Output
按照题目输出
Samples
Hint
n≤50000n≤50000,m≤100000m≤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; }
例二:
题目描述
给出一个NN个顶点MM条边的无向无权图,顶点编号为1-N1−N。问从顶点11开始,到其他每个点的最短路有几条。
输入格式
第一行包含22个正整数N,MN,M,为图的顶点数与边数。
接下来MM行,每行22个正整数x,yx,y,表示有一条顶点xx连向顶点yy的边,请注意可能有自环与重边。
输出格式
共NN行,每行一个非负整数,第ii行输出从顶点11到顶点ii有多少条不同的最短路,由于答案有可能会很大,你只需要输出ans mod 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-51−2−4−5和22条1-3-4-51−3−4−5(由于4-54−5的边有22条)。
对于20\%20%的数据,N ≤ 100N≤100;
对于60\%60%的数据,N ≤ 1000N≤1000;
对于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; } }