最短路径【上海交大复试机试题】【最小生成树】

news/2024/6/18 19:06:21

题目描述

N个城市,标号从0到N-1,M条道路,第K条道路(K从0开始)的长度为2^K,求编号为0的城市到其他城市的最短距离

输入描述:

第一行两个正整数N(2<=N<=100)M(M<=500),表示有N个城市,M条道路
接下来M行两个整数,表示相连的两个城市的编号

输出描述:

N-1行,表示0号城市到其他城市的最短路,如果无法到达,输出-1,数值太大的以MOD 100000 的结果输出。

示例1

输入

复制

4 4
1 2
2 3
1 3
0 1

输出

复制

8
9
11

用大神们的话来说,这是一道披着最短路径外衣的最小生成树的题目。

首先明确一点:1+2^1+2^2+…2^k<2^k+1

刚开始,每一个点属于一个集合,随着最小生成树的建立,最后可以到达的点在一个集合,形成一个连通图

所以,输入的m条边(x,y),每一条都比之前所有边的和要长,

  • 如果x,y在同一个集合,这条边就可以被舍弃了,因为只要xy在一个集合,就说明有从x到y的路径,而这条新路径,一定比已存在的路径要长,所以舍弃
  • 如果x,y不在同一个集合,则这条边就是从x到y的最短路径。到这里还没有完成,需要在所有点中找到和x在一个集合的点j,和y在一个集合的点k,由于xy不在同一集合,显然jk也不在同一集合,这一步的作用就是把jk通过xy联系起来,找到从j到k的最短路径,则dis[j][k]=dis[j][x]+len+dis[y][k],最后Union(x,y)
#include<iostream>

using namespace std;
const int MAXN=101;

int father[MAXN];
int height[MAXN]; 
int dis[MAXN][MAXN];
void Init(int n){
	for(int i=0;i<n;i++){
		father[i]=i;
		height[i]=0;
		for(int j=0;j<n;j++){
			dis[i][j]=0;
		}
	}
}

int powmod(int i){
	int ret=1;
	while(i--){
		ret=(ret*2)%100000;
	}
	return ret;
}

int Find(int i){
	if(i!=father[i]){
		father[i]=Find(father[i]);
	}
	return father[i];
}

void Union(int i,int j){
	i=Find(i);
	j=Find(j);
	if(i!=j){
		if(height[i]>height[j]){
			father[j]=i;
		}
		else if(height[i]<height[j]){
			father[i]=j;
		}
		else {
			father[j]=i;
			height[i]++;
		}
	}
}
int main(){
	int n,m;
	while(scanf("%d%d",&n,&m)!=EOF){
		Init(n);
		int len=1;   //路径长度 1,2^1,2^2,2^3,2^4 
		for(int i=0;i<m;i++){
			int x,y;
			scanf("%d%d",&x,&y);
			if(Find(x)!=Find(y)){   //如果x和y不等,说明他们在两个不同集合中,这条边的长度即为从x到y的最短路径 
				for(int j=0;j<n;j++){
					if(Find(x)==Find(j)){   //x和j属于一个集合 
						for(int k=0;k<n;k++){
							if(Find(y)==Find(k)) {   //y和k属于一个集合,这里的两对分属于两个集合 
								//将jk通过xy相连起来 
								dis[j][k]=dis[k][j]=(dis[j][x]+len+dis[y][k])%100000;
							}
						}
					}
					
				}
			}
			Union(x,y);
			len=len*2%100000;
		    //如果x和y相等,说明他们在同一个集合中,由于1+2+2^2+2^3+…+2^(k-1)<2^k,所以已有的最短路径就是最长的,这条直接舍弃
		}
		int r=Find(0);
		for(int i=1;i<n;i++){
			if(Find(i)!=r){
				dis[0][i]=-1;
			} 
			printf("%d\n",dis[0][i]);
		}
	}
} 

 

 


http://www.niftyadmin.cn/n/852637.html

相关文章

访问MS Access 系统表 MSysObjects ,在SQL SERVER 2005中访问

首先设置MS Access&#xff0c;给予访问MSysObjects 的权限 1. Open Microsoft Access 2. From the Tools menu, select the Options menu option 3. On the View tab, click the System Objects checkbox 4. Click OK to save your changes 5. From the Tools menu, selec…

dirname命令

dirname 命令读取指定路径名删除最后一个“/”&#xff08;斜杠&#xff09;及其后面的字符&#xff0c;保留其他部分&#xff0c;并写结果到标准输出。如果最后一个“/”后无字符&#xff0c;dirname 命令使用倒数第二个“/”&#xff0c;并忽略其后的所有字符。 示例&#xf…

tensorboard坑

一开始打不开&#xff0c;然后是没有激活tensorflow环境&#xff0c;在conda里面激活TensorFlow环境&#xff0c; activate tensorflow 然后把路径转到存的log文件上一级目录&#xff0c;tensorboard --logdirpath

加密,解密,openssl 的基本应用及CA的实现过程

前言进入信息化时代的到来&#xff0c;计算机在我们的工作和生活中扮演着日益重要的角色。用户通过计算机来获取信息、处理信息&#xff0c;同时将自己最重要的信息以数据文件的形式保存在计算机中&#xff0c;方便而快捷的传送给其他用户。但是如果我们的网络中缺少最起码的安…

Legal or Not HDU - 3342 【拓扑排序】

题意&#xff1a;输入n和m&#xff0c;表示有n个人&#xff0c;m对“师傅-徒弟”对应关系&#xff0c;接下来的m行输入“师傅 徒弟"&#xff0c;当n0&#xff0c;m0时break 要判断每一组样例里的关系是否合法&#xff0c;例如“A B”“B A”这样的关系就是不合法的&#…

《统一沟通-微软-实战》-7-配置-4-未分配号码的通知

1. 通知配置先决条件和角色 2. 通知的部署过程 3. 配置通知 4. 配置未分配号码表 5. 验证通知部署 配置未分配号码的通知 通知应用程序是一个企业语音功能&#xff0c;通过该功能&#xff0c;可以配置呼叫未分配分机&#xff08;这些分机可供组织使用但未分配给个人或电话&…

一个排序号的SQL

SELECT ROW_NUMBER() OVER (ORDER BY id DESC) AS rownum, *FROM ft_questionORDER BY id DESC

Python Selenium 常用方法总结

1.获取当前页面的url 方法&#xff1a;current_url 实例&#xff1a;driver.current_url2.获取元素坐标 方法&#xff1a;location 解释&#xff1a;首先查找到你要获取元素的&#xff0c;然后调用location方法 实例&#xff1a;driver.find_element_by_xpath("xpath&…