【2017中国大学生程序设计竞赛 - 女生专场 hdu 6026】【最短路】【思维】【删边构造最短路树方案数】

【链接】

http://acm.hdu.edu.cn/showproblem.php?pid=6026

【题意】

给定一个无向图,删去几条边,得到n个节点的最短路树,求有几种可能性

【思路】

求删边的方法,也就是求树的构造 方法树的构造方法=每条边的选择方法累乘。

弗洛伊德求出每点之间的最短路,计数0-i的每个数的最短路数,相乘即可。 

【代码】

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

const int maxn = 105;
const int inf = 0x3f3f3f3f;
const int mod = 1e9 + 7;
char s[maxn][maxn];
int dis[maxn][maxn];
int cnt[maxn];
int n;

void folyd() {
	for (int k = 0; k < n; k++) {
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < n; j++) {
				dis[i][j] = min(dis[i][j], dis[i][k] + dis[k][j]);
				dis[i][j] %= mod;
			}
		}
	}
}

int main() {
	while (~scanf("%d", &n)) {
		memset(cnt, 0, sizeof(cnt));
		for (int i = 0; i < n; i++) {
			scanf("%s", s[i]);
			for (int j = 0; j < n; j++) {
				if (i == j)dis[i][j] = 0;
				else if (s[i][j] == '0') {
					dis[i][j] = inf;
				}
				else {
					dis[i][j] = s[i][j] - '0';
				}
			}
		}
		folyd();
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < n; j++) {
				if (s[i][j] == '0')continue;
				if (dis[0][i] + s[i][j] - '0' == dis[0][j]) {
					cnt[j]++;
				}
			}
		}
		ll ans = 1;
		for (int i = 1; i < n; i++) {
			ans *= cnt[i];
			ans %= mod;
		}
		printf("%lld\n", ans);
	}
}

猜你喜欢

转载自blog.csdn.net/running_acmer/article/details/82667828
今日推荐