【图论】POJ-1125 Stockbroker Grapevine

这段时间要沉迷刷题一段时间了,就让CSDN陪我一起吧!

一、题目大意

众所周知,股票经纪人对谣言反应过度。您已经签约开发一种在股票经纪人中传播虚假信息的方法,以便为您的雇主提供股票市场的战术优势。为了达到最大效果,您必须以最快的方式传播谣言。
不幸的是,股票经纪人只信任来自“可信来源”的信息。这意味着你必须在开始谣言时考虑他们的联系人的联系关系。特定的股票经纪人需要一定的时间才能将谣言传递给他的每个伙伴。你的任务是编写一个程序,告诉你选择哪个股票经纪人作为谣言的起点,以及谣言传播遍布整个股票经纪人社区的时间。该时间以最后一个人接收信息所需的时间为准。

输入的第一行,股票经纪人的个数N,接下来的N行,每一行开头表示该股票经纪人有的伙伴数,即可以把信息传递的人数M。然后有M个整数对,每个整数对的前一个表示传播人的编号,后一个表示传播所需时间。

二、题目思路以及AC代码

这题考虑问题的时候千万不要局限性,就和我一开始一样…

因为题目要求你求选哪一个作为起点最好,并且输出选择该起点的时间。那么我们就要考虑所有点作为起点应该怎么算,然后再在里面挑取最小的。

假设以编号1的股票经纪人作为起点,那么由于在这道题中,一个人是可以同时开始向其所有伙伴传播消息的,其实是相当于覆盖了所有路径,题目当然要尽可能使时间短,所以我们就算1号股票经纪人传播到每个股票经纪人所用的最少时间(因为在传递的时候覆盖了所有路径,肯定会包含最短路),由于要求所有股票经纪人都了解到传言,所以就要求这些最短路中的最大值,就是以1号作为起点的传播时间了。

知道了以特定点作为起点的传播时间,剩下的也就是枚举,然后求最小值了。(当然,了解思路后也可以直接用Floyd求解).

该题目还有一个判定连通性的问题,我在这里给出一种可行的解决思路,就是利用并查集进行统计,当然也可以采用搜索的方法,这里就都不详细说了(这题的数据比较水… 所以我这里判断顶点的度数都过了 美滋滋)

下面给出AC代码:

Floyd:

#include <iostream>
#define MAXN 110
#define INF 10000000
using namespace std;

int edges[MAXN][MAXN];
int N;

int Max(int a, int b) {
	return a > b ? a : b;
}

void init() {
	for (int i = 0; i < MAXN; i++) {
		for (int j = 0; j < MAXN; j++) {
			if (i == j) edges[i][j] = 0;
			else edges[i][j] = INF;
		}
	}
}

void Floyd() {
	for (int k = 1; k <= N; k++) {
		for (int i = 1; i <= N; i++) {
			for (int j = 1; j <= N; j++) {
				if (edges[i][j] > edges[i][k] + edges[k][j])
					edges[i][j] = edges[i][k] + edges[k][j];
			}
		}
	}
}

bool check() {
	for (int i = 1; i <= N; i++) {
		bool flag = true;
		for (int j = 1; j <= N; j++) {
			if (i == j) continue;
			if (edges[i][j] != INF || edges[j][i] != INF) {
				flag = false;
				break;
			}
		}
		if (flag) {
			return false;
		}
	}
	return true;;
}

int main()
{
	while (scanf("%d", &N) != EOF) {
		init();
		if (!N) break;

		for (int i = 1; i <= N; i++) {
			int M;
			scanf("%d", &M);
			for (int j = 1; j <= M; j++) {
				int v, cost;
				scanf("%d%d", &v, &cost);
				edges[i][v] = cost;
			}
		}

		Floyd();

		if (!check()) {
			printf("disjoint\n");
			continue;
		}

		int resId;
		int min = INF;
		for (int i = 1; i <= N; i++) {
			int max = -INF;
			for (int j = 1; j <= N; j++) {
				max = Max(max, edges[i][j]);
			}

			if (max < min) {
				min = max;
				resId = i;
			}
		}

		printf("%d %d\n", resId, min);
	}

    return 0;
}

如果有问题,欢迎大家指正!

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值