思路
发现最简单的方法就是直接枚举三个点,但是复杂度 \(\Theta(n^3)\) 无法接受。
考虑枚举一个点,并确定它的一条边,那么只需要再枚举一个点了。于是转化为了,对于每一个点找到其最好的出边。
观察下图,\(a \to c\) 的边是不必要的。因为,如果有一个三元环包含 \(a \to c\),那么一定能找到一个不包含 \(a \to c\) 的一条边。
那么,把这种边全部删除,每一个点都将只剩下一条出边,然后枚举另一个点即可。
Code
#include <bits/stdc++.h>
#define re register
using namespace std;
const int N = 5010;
int n,to[N];
char arr[N][N];
inline int read(){
int r = 0,w = 1;
char c = getchar();
while (c < '0' || c > '9'){
if (c == '-') w = -1;
c = getchar();
}
while (c >= '0' && c <= '9'){
r = (r << 3) + (r << 1) + (c ^ 48);
c = getchar();
}
return r * w;
}
int main(){
n = read();
for (re int i = 1;i <= n;i++) scanf("%s",arr[i] + 1);
for (re int i = 1;i <= n;i++){
for (re int j = 1;j <= n;j++){
if (arr[i][j] == '1' && (!to[i] || arr[j][to[i]] == '1')) to[i] = j;
}
}
for (re int i = 1;i <= n;i++){
for (re int j = 1;j <= n;j++){
if (arr[to[i]][j] == '1' && arr[j][i] == '1') return printf("%d %d %d",i,to[i],j),0;
}
}
puts("-1");
return 0;
}
标签:一个点,int,题解,CF117C,while,char,枚举,Cycle
From: https://www.cnblogs.com/WaterSun/p/18322815