描述
题解
并查集+Floyd
算法~
根据题意,无穷大的情况连通块儿一定超过1个,所以先用并查集过一遍,如果是一个连通块儿,那么再用Floyed
算法,求任意两点之间的最短距离,默认每条路径长度为1,最后从所有距离中查找最大的距离,乘以d
即为结果。
代码
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
const int MAXN = 55;
const int INF = 0x3f3f3f3f;
int N, d;
char people[MAXN];
typedef struct
{
int N, E;
int relation[MAXN][MAXN];
} MGraph;
int pre[MAXN];
bool root[MAXN];
MGraph G;
int Floyd(MGraph G)
{
int A[MAXN][MAXN];
int path[MAXN][MAXN];
for (int i = 1; i <= G.N; i++)
{
for (int j = 1; j <= G.N; j++)
{
A[i][j] = G.relation[i][j];
path[i][j] = -1;
}
}
for (int k = 1; k <= G.N; k++)
{
for (int i = 1; i <= G.N; i++)
{
for (int j = 1; j <= G.N; j++)
{
if (A[i][j] > A[i][k] + A[k][j])
{
A[i][j] = A[i][k] + A[k][j];
path[i][j] = k;
}
}
}
}
int res = -1;
for (int i = 1; i <= N; i++)
{
for (int j = 1; j <= N; j++)
{
if (A[i][j] != INF)
{
if (A[i][j] > res)
{
res = A[i][j];
}
}
}
}
return res;
}
void init()
{
for (int i = 1; i <= N; i++)
{
pre[i] = i;
}
memset(G.relation, 0x3f, sizeof(G.relation));
G.N = N;
G.E = 0;
memset(root, false, sizeof(root));
return ;
}
int find(int x)
{
int r = x;
while (r != pre[r])
{
r = pre[r];
}
int s = x, tmp;
while (pre[s] != r)
{
tmp = pre[s];
pre[s] = r;
s = tmp;
}
return r;
}
void join(int x, int y)
{
int fx = find(x);
int fy = find(y);
if (fx != fy)
{
pre[fx] = fy;
}
return ;
}
int main(int argc, const char * argv[])
{
int T;
cin >> T;
while (T--)
{
cin >> N >> d;
init();
for (int i = 0; i < N; i++)
{
scanf("%s", people);
for (int j = 0; j < N; j++)
{
if (people[j] == 'Y')
{
G.relation[i + 1][j + 1] = 1; // 默认路径长度为1
G.E++;
join(i + 1, j + 1);
}
else if (i == j)
{
G.relation[i + 1][j + 1] = 0;
}
}
}
for (int i = 1; i <= N; i++)
{
root[find(i)] = true;
}
int res = 0;
for (int i = 1; i <= N; i++)
{
if (root[i])
{
res++;
}
}
// 如果连通块超过一个则输出-1
if (res > 1)
{
cout << "-1\n";
continue;
}
int ans = Floyd(G);
cout << ans * d << '\n';
}
return 0;
}