Emulator(Dijkstra)

描述

有一个n个点的无向正权图G,这个图是连通的,小Y知道这些点两两之间的最短路的长度。

小J想要构造一个新的无向正权图G',使得新图中两两之间的最短路的长度与原图一样,并且边数最少。

输入

第一行一个整数n,表示点的个数。

接下来n行,每行n个整数。第i行第j个整数表示i点到j点的在G中的最短路长度,保证合法。

1<=n<=300,保证图G中最短路长度不超过109

输出

一个整数表示新图G'的最小的边数。

样例输入
4
0 1 3 6
1 0 2 5
3 2 0 3
6 5 3 0
样例输出
3
思路:依次求每一个顶点的最短路径图,假设从该顶点出发的距离小于等于其它边之和,则标记它。
#include<iostream>
#include<cstdio>
#define INF 100000000
using namespace std;

int main() {
	int  n;
	cin >> n;
	int Map[305][305];
	int dis[305][305];
	bool flag1[305][305];//判断i点到j点是否被存入
	bool flag2[305][305];//判断边ij是否被去除
	for(int i=1;i<=n;i++)
		for (int j = 1; j <= n; j++) {
			cin >> Map[i][j];
			dis[i][j]=Map[i][j];
			flag2[i][j]=flag1[i][j] =false;
		} 
	for (int i = 1; i <= n; i++) {
		int t = n-1;
		//最短路径算法Dijkstra
		while (t--) {
			int min = INF;
			int temp;
			for (int j = 1; j <= n; j++) 
				if (i!=j&&!flag1[i][j] &&dis[i][j] < min) {
					min = dis[i][j];
					temp = j;
				}
			flag1[i][temp] = true;
			for (int j = 1; j <= n; j++) {
				if (i!=j&&!flag1[i][j] && dis[i][j]>= dis[i][temp] + Map[temp][j]) {
					dis[i][j] = dis[i][temp] + Map[temp][j];
					flag2[i][j] = true;
				}
			}
		}
	}
	int e = n*(n - 1) / 2;//总的边数
	int cnt = 0;
	for (int i = 1; i <= n; i++) 
		for (int j = 1; j <= n; j++)
			if (flag2[i][j])
				cnt++;
	e = e-cnt / 2;
	cout << e << endl;
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值