【2020.2.7 练习赛】 T4-最短路计数(图论-SPFA)

来源:JZOJ

题目描述

给出一个 N N N 个顶点 M M M 条边的无向无权图,顶点编号为 1 ∼ N 1∼N 1N

问从顶点 1 1 1 开始,到其他每个点的最短路有几条。

解题思路

  • 这是一道 S P F A SPFA SPFA 最短路,只需在 S P F A SPFA SPFA 的模板上稍加改动就可以 A C AC AC,算是比较套路了;
  • 具体怎么实现呢?我们不妨设想,
  • 如果 d i s [ x ] + 1 = = d i s [ y ] dis[x]+1==dis[y] dis[x]+1==dis[y]( d i s [ x ] dis[x] dis[x]表示根节点到 x x x的距离),是不是说明找到了第二条最短路?思考一下;
  • 所以,这样我们就可以写代码了,用 a n s [ x ] ans[x] ans[x] 表示根节点到 x x x 的最短路条数;

美妙的 C o d e Code Code时间

#include 
using namespace std;
int q[400005],linkk[100005],ans[100005],dis[100005],vis[100005];
int n,m,tot=0;
struct node
{
	int y,next;
}e[400005];
void insert(int x,int y)  //邻接表
{
	e[++tot].y=y;
	e[tot].next=linkk[x]; linkk[x]=tot;
}
void SPFA(int st)
{
	for (int i=1;i<=n;i++) dis[i]=1e9;
	memset(vis,0,sizeof(vis));
	dis[st]=0; vis[st]=1;
	ans[st]=1;
	int head=1,tail=1;
	q[1]=st;
	for (head=1;head<=tail;head++)
	{
		int x=q[head];  //取出队头
		for (int i=linkk[x];i;i=e[i].next)
		{
			int y=e[i].y;
			if (dis[x]+1<dis[y])  //迭代
			{
				dis[y]=dis[x]+1;  //更新
				ans[y]=ans[x];
				if (!vis[y])
				{
					q[++tail]=y;  //进队
					vis[y]=1;  //标记
				}
			}
			else
			if (dis[x]+1==dis[y])
			{
				ans[y]=(ans[x]+ans[y])%100003;  //累加
			}
		}
		vis[x]=0;  //出队
	}
}
int main()
{
	freopen("shortest.in","r",stdin);
	freopen("shortest.out","w",stdout);
	scanf("%d %d",&n,&m);
	for (int i=1;i<=m;i++)
	{
		int x,y;
		scanf("%d %d",&x,&y);
		insert(x,y);  //邻接表插入
		insert(y,x);
	}
	SPFA(1);
	for (int i=1;i<=n;i++)
	{
		if (dis[i]==1e9) printf("0\n");  //如果没有最短路
		 else printf("%d\n",ans[i]);
	}
	return 0;
}

你可能感兴趣的:(练习赛/模拟赛,#,图论-最短路,图论)