常规的最短路计数问题:注意有重边(重边不用理,看样例),自环(读入时过滤)。
另外这个无向图没有权,其实可以直接bfs做,但考虑到以后带权的情况,按spfa走了。
水题被卡了三次(嘤嘤嘤
第一次40pts:忘取膜了(???
第二次80pts:加了多余的判断,实质还是思路不清晰。
第三次100pts:去了冗余的判断,终于A了。
思路:
记录f数组表示f[i]为以i为终点,1为起点的最短路条数。初始只有f[1]=1。
其余在松弛的时候如果更新,f[v]=f[u];
如果恰好相等(有相同最短路径)(这种情况不能和上面的情况一起判断),就f[v]+=f[u]
Code
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<queue>
using namespace std;
const int inf=;
int n,m,s;
int p=;
int num;
int pre[],f[];
struct node{
int to,val,next;
}edge[];
int dis[];
bool visit[];
void add(int x,int y,int z)
{
num++;
edge[num].val=z;
edge[num].to=y;
edge[num].next=pre[x];
pre[x]=num;
}
void spfa()
{
queue<int>q;
for(int i=;i<=n;i++)
dis[i]=inf;
q.push();
dis[]=;f[]=;
visit[]=;
while(!q.empty())
{
int u=q.front();
q.pop();
visit[u]=;
for(int i=pre[u];i>;i=edge[i].next)
{
int v=edge[i].to;
//if(u==1) (f[v]=1)%=p;
if(dis[v]>dis[u]+edge[i].val)
{
dis[v]=dis[u]+edge[i].val;
/*if(u!=1)*/ (f[v]=f[u])%=p;
if(visit[v]==)
{
visit[v]=;
q.push(v);
}
}
else if(dis[v]==dis[u]+edge[i].val)
(f[v]+=f[u])%=p;
}
}
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=;i<=m;i++)
{
int x=,y=,z=;
scanf("%d%d",&x,&y);
if(x==y) continue;
add(x,y,);
add(y,x,);
}
spfa();
for(int i=;i<=n;i++)
printf("%d\n",f[i]);
return ;
}
* Update 2018.9.22
做NOIp2017逛公园的时候发现自己的最短路计数算法有些Bug==
导致30分没有成功拿到。
做了一道加强版的最短路计数 路径统计
#include<cstdio>
#include<algorithm>
#include<queue>
#include<cstring> using namespace std;
typedef long long ll; int n,m,fake;
int vis[],dis[];
ll f[];
int e[][]; void spfa()
{
memset(dis,,sizeof(dis));
fake=dis[];
queue<int>q;
q.push();vis[]=;dis[]=;f[]=;
while(!q.empty())
{
int u=q.front();q.pop();
vis[u]=;
if(u==n) continue;
for(int i=;i<=n;i++)
{
if(dis[i]==dis[u]+e[u][i])
f[i]+=f[u];
if(dis[i]>dis[u]+e[u][i])
{
dis[i]=dis[u]+e[u][i];
f[i]=f[u];
}
if(f[i]&&!vis[i]) vis[i]=,q.push(i);
}
f[u]=;
}
} int main()
{
scanf("%d%d",&n,&m);
memset(e,,sizeof(e));
for(int i=;i<=m;i++)
{
int x=,y=,z=;
scanf("%d%d%d",&x,&y,&z);
e[x][y]=min(e[x][y],z);
}
spfa();
if(fake==dis[n]) printf("No answer");
else printf("%d %lld",dis[n],f[n]);
return ;
}
还是用这个吧qwq