• 洛谷 P1144 最短路计数 题解


    P1144 最短路计数

    题目描述

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

    输入格式

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

    接下来(M)行,每行(2)个正整数(x,y),表示有一条顶点(x)连向顶点(y)的边,请注意可能有自环与重边。

    输出格式

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

    输入输出样例

    输入 #1

    5 7
    1 2
    1 3
    2 4
    3 4
    2 3
    4 5
    4 5

    输出 #1

    1
    1
    1
    2
    4

    说明/提示

    (1)(5)的最短路有(4)条,分别为(2)(1-2-4-5)(2)(1-3-4-5)(由于(4-5)的边有(2)条)。

    对于(20\%)的数据,(N ≤ 100)

    对于(60\%)的数据,(N ≤ 1000)

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

    【思路】

    最短路 , dijkstra

    【题目大意】

    从1到每一个点的最短路有多少条

    【核心思路】

    最短路有多少条?
    完全可以在dijkstra或者SPFA的过程中求出来的
    因为在松弛操作的时候
    用y到x的边去松弛
    如果这条边替换上去会使1到x的距离更近
    那这个时候x的答案就会变为松到他y的最短路的个数
    如果这条边替换上去和原来一样
    那就是目前看来可以当做最短路
    在x原来最短路个数的基础上加上到点y最短路的个数就可以了

    【完整代码】

    #include<iostream>
    #include<cstdio>
    #include<queue>
    #include<cstring>
    
    using namespace std;
    
    int read()
    {
    	int sum = 0,fg = 1;
    	char c = getchar();
    	while(c < '0' || c > '9')
    	{
    		if(c == '-')fg = -1;
    		c = getchar();
    	}
    	while(c >= '0' && c <= '9')
    	{
    		sum = sum * 10 + c - '0';
    		c = getchar();
    	}
    	return sum * fg;
    }
    const int Max = 2000006;
    const int mo = 100003;
    struct node
    {
    	int y,ne;
    }a[Max << 1];
    int head[Max >> 1],sum = 0;
    
    void add(int x,int y)
    {
    	a[++ sum].y = y;
    	a[sum].ne = head[x];
    	head[x] = sum;
    }
    
    struct point
    {
    	int x;
    	int w;
    	bool operator < (const point xx) const
    	{
    		return xx.w < w;
    	}
    };
    int dis[Max >> 1];
    priority_queue<point>q;
    int ans[Max >> 1];
    bool use[Max >> 1];
    void dj()
    {
    	memset(dis,0x3f,sizeof(dis));
    	dis[1] = 0;
    	ans[1] = 1;
    	q.push((point){1,0});
    	while(!q.empty())
    	{
    		point qwq = q.top();
    		q.pop();
    		int x = qwq.x,w = qwq.w;
    		if(use[x] == true)
    			continue;
    		else
    			use[x] = true;
    		for(register int i = head[x];i != 0;i = a[i].ne)
    		{
    			int awa = a[i].y;
    			if(dis[awa] > dis[x] + 1)
    			{
    				dis[awa] = dis[x] + 1;
    				ans[awa] = ans[x];
    				if(use[awa] == false)
    					q.push((point){awa,dis[awa]});
    			}
    			else
    			if(dis[awa] == dis[x] + 1)
    			{
    				ans[awa] += ans[x];
    				ans[awa] %= mo;
    			}
    		}
    	}
    }
    
    int main()
    {
    	int n = read(),m = read();
    	for(register int i = 1;i <= m;++ i)
    	{
    		int x = read(),y = read();
    		add(x,y);
    		add(y,x);
    	}
    	dj();
    	for(register int i = 1;i <= n;++ i)
    		cout << ans[i] << endl;
    	return 0;
    }
    
  • 相关阅读:
    十条jQuery代码片段助力Web开发效率提升
    C#如何释放已经加载的图片 (转)
    获取文件夹下最新文件 (转)
    时间格式转换
    调整ListBox控件的行间距及设置文本格式
    c++builder调用vc的dll
    mws文件中的tab文件改为相对路径
    .net 对配置文件内容的操作
    winform下mapxtreme2008 v7.0 生成release版提示找不到dll问题
    vue实现按字母A-Z选择城市
  • 原文地址:https://www.cnblogs.com/acioi/p/11812959.html
Copyright © 2020-2023  润新知