FZU - 2271 X (Floyd)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/GYH0730/article/details/79976642

题意:给出n个点,m条边,在保持任意两点之间最短路径距离不变的情况下,最多可以去除多少边?

思路:在输入数据的时候,可以去除一些边,因为我们只需要两个点之间距离最小的那条边,然后跑一遍Floyd算法,求出任意两点的最短路,如果两个点是直接相连,并且被松弛过,或者松弛之后的距离与两点直接相连的距离相等,我们就可以去除这条两点之间直接相连的边。

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<string>
#include<map>
#include<vector>
#include<queue>
#include<stack>
#include<set>
#include<algorithm>
#define MAX 105
#define INF 0x3f3f3f3f
#define MOD 1000000007
using namespace std;
typedef long long ll;

int e[MAX][MAX];
int ee[MAX][MAX];
int cnt[MAX][MAX];
int is[MAX][MAX];

int main(void)
{
	int t,n,m,i,j,k;
	scanf("%d",&t);
	int cas = 0;
	
	while(t--){
		
		int n,m;
		scanf("%d%d",&n,&m);
		memset(cnt,0,sizeof(cnt));
		memset(is,0,sizeof(is));
		memset(ee,0,sizeof(ee));
		
		for(int i = 1; i <= n; i++){
			for(int j = 1; j <= n; j++){
				if(i == j){
				   e[i][j] = 0;
			    }
			else{
				   e[i][j] = INF;
			    }
			}
		}
		
		int ans = 0;
		for(int i = 1; i <= m; i++){
			int a,b,w;
			scanf("%d%d%d",&a,&b,&w);
			//保留最小的边的距离 
			e[a][b] = e[b][a] = min(e[a][b],w);
			//记录两点之间边的数量 
			cnt[a][b]++;
			cnt[b][a]++;
			//记录两点之间是否有边相连 
			ee[a][b] = ee[b][a] = 1;
		}
		
		for(int i = 1; i <= n; i++){
			for(int j = i + 1; j <= n; j++){
				if(cnt[i][j] > 0){
					//两点之间我们只需要那条最短边,其余的都舍去 
					ans += cnt[i][j] - 1;
				}
			}
		}

		
		for(int k = 1; k <= n; k++){
			for(int i = 1; i <= n; i++){
				for(int j = 1; j <= n; j++){

					if(i == k){
						continue;
					}
					if(j == k){
						continue;
					}
					//标记被松弛的以及松弛之后距离与原来相等的 
					if(e[i][j] >= e[i][k] + e[k][j]){
						e[i][j] = e[i][k] + e[k][j];
						is[i][j] = is[j][i] = 1;
					}
				}
			}
		}
		
		for(int i = 1; i <= n; i++){
			for(int j = i + 1; j <= n; j++){
				if(is[i][j] && ee[i][j]){
					ans++;
				}
			}
		}
		printf("Case %d: %d\n",++cas,ans);
	
	}
	return 0;
}

阅读更多
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页