ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

《算法竞赛进阶指南》0x62 T4 黑暗城堡

2021-06-02 16:33:52  阅读:270  来源: 互联网

标签:进阶 val int T4 edge lsp Lord 0x62 dis


题目传送门

题目描述

在顺利攻破 Lord lsp 的防线之后,lqr 一行人来到了 Lord lsp 的城堡下方。

Lord lsp 黑化之后虽然拥有了强大的超能力,能够用意念力制造建筑物,但是智商水平却没怎么增加。

现在 lqr 已经搞清楚黑暗城堡有 N 个房间,M 条可以制造的双向通道,以及每条通道的长度。

lqr 深知 Lord lsp 的想法,为了避免每次都要琢磨两个房间之间的最短路径,Lord lsp 一定会把城堡修建成树形的。

但是,为了尽量提高自己的移动效率,Lord lsp 一定会使得城堡满足下面的条件:

设 D[i] 为如果所有的通道都被修建,第 i 号房间与第 1 号房间的最短路径长度;而 S[i] 为实际修建的树形城堡中第 i 号房间与第 1 号房间的路径长度;要求对于所有整数 i,有 S[i]=D[i] 成立。

为了打败 Lord lsp,lqr 想知道有多少种不同的城堡修建方案。

你需要输出答案对 231–1 取模之后的结果。

输入格式

第一行有两个整数 N 和 M。

之后 M 行,每行三个整数 X,Y 和 L,表示可以修建 X 和 Y 之间的一条长度为 L 的通道。

输出格式

一个整数,表示答案对 231–1 取模之后的结果。

数据范围

2 ≤ N ≤ 1000 , 2≤N≤1000, 2≤N≤1000,
N − 1 ≤ M ≤ N ( N − 1 ) / 2 , N−1≤M≤N(N−1)/2, N−1≤M≤N(N−1)/2,
1 ≤ L ≤ 100 1≤L≤100 1≤L≤100

输入样例:

3 3
1 2 2
1 3 1
2 3 1

输出样例:

2

题解

这道题目实际上就是要求最短路径生成树的数量
首先引出一个概念,什么是最短路径生成树?
即在我们生成的这棵树中,从源点到每个点的路径与在无向图之中源点到每个点的最短路大小相等
因此我们首先需要知道在无向图中,源点到每个点的最短路大小
跑一遍Dijkstra就ok了
我们可以遍历每条边,如果 d i s [ x ] + e d g e [ i ] . v a l dis[x]+edge[i].val dis[x]+edge[i].val恰好等于 d i s [ y ] dis[y] dis[y],那么我们就可以有一种到达节点 y y y的路径,可以统计有到达每个节点的路径有多少种,即每当满足上述条件,我们使 c n t [ y ] + + cnt[y]++ cnt[y]++,根据乘法原理,将到达每个节点路径数相乘,即为可以生成的最小路径生成树的数量

code
#include<bits/stdc++.h>
using namespace std;
const int N=1010;
const int M=N*(N-1)/2;
int n,m;
struct node
{
	int nxt,to,val;
}edge[2*M];
int head[N],tot=0;
void Lian(int x,int y,int z)
{
	tot++;
	edge[tot].to=y;
	edge[tot].nxt=head[x];
	edge[tot].val=z;
	head[x]=tot;
}
struct Point
{
	int d,p;
	bool operator<(const Point &x)const{
		return d>x.d;	
	}
};
int dis[N];
bool vis[N];
void dijkstra()
{
	memset(dis,0x3f,sizeof(dis));
	priority_queue<Point> q;
	dis[1]=0;
	Point a;
	a.d=0,a.p=1;
	q.push(a);
	while(!q.empty())
	{
		a=q.top();
		q.pop();
		int x=a.p;
		if(vis[x]) continue;
		vis[x]=1;
		for(int i=head[x];i;i=edge[i].nxt)
		{
			int y=edge[i].to;
			if(dis[x]+edge[i].val<dis[y])
			{
				dis[y]=edge[i].val+dis[x];
				a.p=y,a.d=dis[y];
				q.push(a);
			}
		}
	}
}
long long cnt[N];
const int Mod=(1<<31)-1;
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=m;i++)
	{
		int x,y,l;
		scanf("%d%d%d",&x,&y,&l);
		Lian(x,y,l);
		Lian(y,x,l);
	}
	dijkstra();
	cnt[1]=1;
	for(int i=1;i<=n;i++)
		for(int j=head[i];j;j=edge[j].nxt)
		{
			int y=edge[j].to;
			if(dis[i]+edge[j].val==dis[y]) cnt[y]++;
		}
	long long ans=1;
	for(int i=1;i<=n;i++) ans=ans*cnt[i]%Mod;
	cout<<ans;
	return 0;
 } 

标签:进阶,val,int,T4,edge,lsp,Lord,0x62,dis
来源: https://blog.csdn.net/weixin_55355427/article/details/117472391

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有