题目链接:[CodeForces500B]New Year Permutation[floyd]
题意分析:矩阵中s[i][j] == '1' 时,对应的a[i], a[j]可进行互换,问:根据矩阵,多次互换后最终可以得到字典序最小的序列是什么?
解题思路:既然要求字典序最小,那就尽量把小的往前排。那么怎么样尽量往前排呢?就是遍历所以该点能到达的点,让最小的,并且排在这个点后面的点与它交换即可。怎样遍历到所有能到达的点呢?这个时候就要用到floyd了。
个人感受:表示题意好难懂TAT。然后遍历所有能到的点,之前想的是dfs,然后各种debug。还是floyd大法好呀~
具体代码如下:
#include <iostream>
#include <cstdio>
using namespace std;
const int MAXN = 310;
int a[MAXN];
char s[MAXN][MAXN];
int main() {
int n;
scanf("%d", &n);
for (int i = 0; i < n; ++i)
scanf("%d", a + i);
for (int i = 0; i < n; ++i)
scanf("%s", s[i]);
for (int i = 0; i < n; ++i)
for (int j = 0; j < n; ++j)
for (int k = 0; k < n; ++k)
if (s[j][i] == '1' && s[i][k] == '1') //没有必要硬去记什么在内什么在外,只要记住最外层代表的是中间的连接点,floyd就很好记的
s[j][k] = '1';
for (int i = 0; i < n; ++i)
{
int mi = a[i]; //记录最小值
int p = i; //记录最小值对应的坐标
for (int j = 0; j < n; ++j)
{
if (s[i][j] == '1' && mi > a[j] && p < j) //值小,且排在后面的点
{
mi = a[j];
p = j;
}
}
swap(a[i], a[p]);
}
for (int i = 0; i < n - 1; ++i)
printf("%d ", a[i]);
printf("%d\n", a[n - 1]);
return 0;
}