思路:
1、首先我们考虑这样一种情况:
4 d
NYNN
YNNN
NNNY
NNYN
很显然此时1和2是朋友,3和4是朋友,但是我们无法通过一个人的金钱数来判断其他所有人的金钱数,那么对应这种情况就是-1.
那么我们使用并查集来判断,是否整个图是连通的,如果不是连通的,那么对应输出-1.如果是连通的,我们继续处理。
2、对应我们有一个关系网络,是一个连通图,并且我们已知两个直接朋友之间的贫富差距最大为D,那么我们只要找到了一条最长路,那么我们对应就可以设定起点的金钱数为x,那么终点的金钱数就是x+d*最长路的长度。
因为点的个数不多,那么我们暴力处理两点间最短距离使用Floyd算法即可,然后我们枚举维护一条最长路。答案就是最长路的长度*d。
建图的时候只要把Y的地方设定两点之间距离为1即可。
Ac代码:
#include<stdio.h> #include<string.h> #include<iostream> using namespace std; char a[55][55]; int map[55][55]; int f[55]; int n,d; int find(int a) { int r=a; while(f[r]!=r) r=f[r]; int i=a; int j; while(i!=r) { j=f[i]; f[i]=r; i=j; } return r; } void merge(int a,int b) { int A,B; A=find(a); B=find(b); if(A!=B) f[B]=A; } int judge() { for(int i=0;i<n;i++)f[i]=i; for(int i=0;i<n;i++) { for(int j=0;j<n;j++) { if(map[i][j]==1) { merge(i,j); } } } int cnt=0; for(int i=0;i<n;i++) { if(f[i]==i)cnt++; } if(cnt==1)return 1; else return 0; } int main() { int t; scanf("%d",&t); while(t--) { memset(map,0x3f3f3f3f,sizeof(map)); scanf("%d%d",&n,&d); for(int i=0;i<n;i++)map[i][i]=0; for(int i=0;i<n;i++) { scanf("%s",a[i]); for(int j=0;j<n;j++) { if(a[i][j]=='Y')map[i][j]=1; } } if(judge()==0) { printf("-1\n"); continue; } for(int i=0;i<n;i++) { for(int j=0;j<n;j++) { for(int k=0;k<n;k++) { map[j][k]=min(map[j][k],map[j][i]+map[i][k]); } } } int output=-1; for(int i=0;i<n;i++) { for(int j=0;j<n;j++) { if(map[i][j]==0x3f3f3f3f||i==j)continue; output=max(output,map[i][j]); } } if(output==-1)printf("-1\n"); else printf("%d\n",output*d); } } 效率榜第一的思路:
如果我们一个图保证是连通的,那么对应Floyd求出的最短路一定没有inf这一种情况发生,那么对应维护最大值的时候,如果最终维护出来的最大值是inf,那么对应一定就是因为整个图不连通的原因,那么对应此时输出-1即可。
(优化了大部分代码量啊................(还是我太天真,为毛非要用个并查集呢));
Ac代码(感谢效率榜第一mostleg分享的代码):
#include <cstdio> #include <algorithm> #include <iostream> #include <string> #include <vector> #include <set> #include <cmath> #include <stack> using namespace std; int n,d; string con[50]; int dis[50][50]; void init() { cin >> n >> d; for (int i = 0; i < n; i++) { cin >> con[i]; } } int work() { for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { dis[i][j] = (con[i][j] == 'Y' ? 1 : 9999); } dis[i][i] = 0; } 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]); } } } int cur = 0; for (int i = 0; i < n; i++) { for (int j = i + 1; j < n; j++) { cur = max(dis[i][j], cur); } } if (cur >= n) { return -1; } return cur * d; } int main() { int T; cin >> T; for (; T; T--) { init(); cout << work() << endl; } return 0; }
