题意
题目意思并不难理解,其给出我们由n个点组成的有向图,并以一个矩阵的形式给出,在矩阵的第i行第j列为点i到j的有向边,若此两点之间有边,这两点之间的有向边用一个小写字母给出,若没有边,则为“-”, 要求我们找出任意两点间的最短回文路径(首先保证这条路径为回文路径 ,其次为这两点间的回文路径里最短的),以矩阵形式输出,若不存在则输出“-1”。
思路
毫无疑问,这是一个最短路问题,需要用到bfs来解决, 但是难点在于如何保证搜出的路径为回文路径(“aabaa”,“aba”,“abba”,“a”均符合回文的要求),如果暴力枚举去检查每搜出来的路径是否为回文路径显然并不可行,那么我们考虑到一种递归的思想,如果想要找出从k到l的合法路径,即只要从i到j之间的路径有合法路径,那么只要保证从k到i,j到l,存在路径并且C(k,i)=C(j,l),那么这条路径必定为我们所找的k到l之间的合法路径。
下面我们就要对不同的情况进行处理:
1.若为(i, i)则直接可以到达本身,则路径的权值为0。
2.对于(i, j)只要C(i, j)
"-",则他们之间的路径权值为1。
3.对于(k, l)只要C(k, i)
"-",且只要C(j, l)
"-",同时只要C(k, i) = C(j, l) ,那么其权值就是在(i, j)的基础上加2。
代码
#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
#define endl '\n'
#define F first
#define S second
#define PII pair<int, int>
using namespace std;
signed main()
{
int n;
cin >> n;
vector<vector<int>> a(n, vector<int>(n, 0x3f3f3f3f));
vector<vector<char>> c(n, vector<char>(n));
for(int i = 0; i < n; ++ i)
for(int j = 0; j < n; ++ j) cin >> c[i][j];
queue<PII> q;
for(int i = 0; i < n ;++ i)
{
q.push({i, i});
a[i][i] = 0;
}
for(int i = 0; i < n;++ i)
for(int j = 0; j < n; ++ j)
{
if(i == j || c[i][j] == '-') continue;
q.push({i, j});
a[i][j] = 1;
}
while(q.size())
{
auto p = q.front();
q.pop();
for(int i = 0; i < n; ++ i)
for(int j = 0; j < n; ++ j)
{
if(c[i][j] == '-' && a[i][j] == 0x3f3f3f3f && c[i][p.F] != '-' && c[p.S][j] != '-' && c[i][p.F] == c[p.S][j])
{
a[i][j] = a[p.F][p.S] + 2;
q.push({i, j});
}
}
}
for(int i = 0; i < n; ++ i)
{
for(int j = 0; j < n; ++ j)
{
if(a[i][j] == 0x3f3f3f3f) cout << -1 << ' ';
else cout << a[i][j] << ' ';
}
cout << endl;
}
}