51nod oj 1366 贫富差距【枚举+最长的短路】

本文解析了一道来自TopCoder的算法题——贫富差距问题,通过分析题目要求和给出一种有效的解决思路,利用图论中的概念来确定一个国家内最大贫富差距的下界。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目来源:  TopCoder
基准时间限制:1 秒 空间限制:131072 KB 分值: 40  难度:4级算法题
 收藏
 关注
一个国家有N个公民,标记为0,1,2,...,N-1,每个公民有一个存款额。已知每个公民有一些朋友,同时国家有一条规定朋友间的存款额之差不能大于d。也就是说,a和b是朋友的话,a有x元的存款,b有y元,那么|x-y|<=d。给定d值与N个人的朋友关系,求这个国家最富有的人和最贫穷的人的存款相差最大的可能值是多少?即求贫富差距的最大值的下界。若这个值为无穷大,输出-1.
Input
多组测试数据,第一行一个整数T,表示测试数据数量,1<=T<=5
每组测试数据有相同的结构构成。
每组数据的第一行两个整数N,d,表示人数与朋友间存款差的最大值,其中2<=N<=50,0<=d<=1000.
接下来有一个N*N的数组A,若A[i][j]='Y'表示i与j两个人是朋友,否则A[i][j]='N'表示不是朋友。其中A[i][i]='N',且保证
A[i][j]=A[j][i].
Output
每组数据一行输出,即这个国家的贫富差距最大值的下界,如果这个值为无穷大输出-1.
Input示例
3
3 10
NYN
YNY
NYN
2 1
NN
NN
6 1000
NNYNNN
NNYNNN
YYNYNN
NNYNYY
NNNYNN
NNNYNN
Output示例
20
-1
3000


开始用树的直径,不出意外的WA了;

此题的联通路不是一个树---

如图:


如果按照树的直径的做法---第一次可能搜到B点--从B点再开始搜答案为1


毫无疑问:答案为2----


即:树的直径只适用于树上--------



最多50个点----

枚举最富的点====然后求最长的短路----

时间复杂度:O(n^3)



代码:

#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
int n,d;
char map[1010][1010];
int fer[1010];
struct node{
	int hao,step;
}now,qian;
int find(int xx)
{
	if (xx==fer[xx])
	return xx;
	return fer[xx]=find(fer[xx]);
}
bool fafe[1010];
int dfs(int xx)
{
	memset(fafe,true,sizeof(fafe));
	fafe[xx]=false;
	now.hao=xx;
	now.step=0;
	queue<node> que;
	que.push(now);
	int lp,yy;
	while (!que.empty())
	{
		now=que.front();
		que.pop();
		lp=now.hao;
		yy=now.step;
		for (int i=0;i<n;i++)
		{
			if (map[lp][i]=='Y'&&fafe[i])
			{
				fafe[i]=false;
				qian.hao=i;
				qian.step=now.step+1;
				que.push(qian);
			}
		}
	}
	return yy;
}
int main()
{
	int t;scanf("%d",&t);
	while (t--)
	{
		scanf("%d%d",&n,&d);
		for (int i=0;i<n;i++)
		{
			scanf("%s",map[i]);
			fer[i]=i;
		}
		for (int i=0;i<n;i++)
			for (int j=i+1;j<n;j++)
				if (map[i][j]=='Y')
					fer[find(i)]=find(j);
		int s=0;
		for (int i=0;i<n;i++)
			if (fer[i]==i)
				s++;
		if (s>1)
		{
			printf("-1\n");
			continue;
		}
		int p,ans=0;
		for (int i=0;i<n;i++)
		{
			int p=dfs(i);
			ans=max(p,ans);
		}
		printf("%d\n",d*ans);
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值