CC 采用 $\text{CC BY-NC-SA 4.0}$ 许可,转载请注明:“转自 【算法】最小环”
在本文中,记 $N = | V | $, $M = | E | $。 |
for(int k = 1; k <= n; k++) {
for(int i = 1; i < k; i++)
for(int j = i + 1; j < k; j++) //注意i!=j
ans = min(ans, f[i][j] + M[i][k] + M[k][j]);
for(int i = 1; i <= n; i++)
for(int j = 1; j <= n; j++)
f[i][j] = f[j][i] = min(f[i][j], f[i][k] + f[k][j]);
}
正确代码:
#include <bits/stdc++.h>
using namespace std;
typedef pair <int, int> pi;
typedef long long LL;
const int P = 998244353;
const int INF = 0x3f3f3f3f;
const LL INFLL = 0x3f3f3f3f3f3f3f3fll;
const int N = 1e6 + 5;
int n, m, ans = INF;
vector <int> E[N];
set <pi> S;
int vis[N], dis[N];
namespace math {
int minp[N], prime[N], p_cnt;
void prime_table(int n) {
p_cnt = 0;
for(int i = 1; i <= n; i++) minp[i] = i;
for(int i = 2; i <= n; i++) {
if(minp[i] == i) prime[++p_cnt] = i;
for(int j = 1; prime[j] <= minp[i]; j++) {
if(j > p_cnt) break;
if(1ll * i * prime[j] <= n) minp[i * prime[j]] = prime[j];
else break; //important
}
}
}
};
using namespace math;
void bfs(int s) {
int flag = 0;
queue <pi> Q;
Q.push(make_pair(s, -1));
vis[s] = true;
while(Q.empty() == false) {
int u = Q.front().first, pre = Q.front().second;
Q.pop();
for(auto v: E[u]) {
if(v == pre) continue;
if(vis[v] == false) {
if(u == s) vis[v] = ++flag;
else vis[v] = vis[u];
dis[v] = dis[u] + 1;
Q.push(make_pair(v, u));
}
else if(vis[u] != vis[v]) {
ans = min(ans, dis[u] + dis[v] + 1);
}
}
}
}
void init() {
int u, v, x;
scanf("%d", &n);
prime_table(1e6);
for(int i = 1; i <= n; i++) {
scanf("%d", &x);
u = minp[x];
if(u != 1) {
int flag = 0;
while(x % u == 0) x /= u, flag ^= 1;
if(!flag) u = 1;
}
v = minp[x];
if(v != 1) {
int flag = 0;
while(x % v == 0) x /= v, flag ^= 1;
if(!flag) v = 1;
}
if(u == v) return (void) printf("1\n");
if(u > v) swap(u, v);
if(S.count(make_pair(u, v))) ans = 2;
else S.insert(make_pair(u, v));
E[u].push_back(v);
E[v].push_back(u);
}
prime[0] = 1;
for(int i = 1; i <= 1000; i++) {
if(minp[i] != i) continue;
for(int i = 0; i <= p_cnt; i++) vis[prime[i]] = dis[prime[i]] = 0;
bfs(i);
}
if(ans < INF) printf("%d\n", ans);
else printf("-1\n");
}
int main() {
//ios::sync_with_stdio(false);
init();
return 0;
}
错误处理方式:
fpd = lower_bound(prime + 1, prime + Index + 1, 1000) - prime;
for(int i = fpd; i <= Index; i++) {
for(auto u: E[i])
for(auto v: E[i])
if(u < v) {
if(M[u][v] == 1) return (void) printf("3\n");
if(M[u][v] == 2) ans = 4;
M[u][v] = M[v][u] = min(M[u][v], 2);
}
}
/*
把形如<小, 大>, <大, 小>的路径压成了长度为2的一条边。
但是会导致三个大长度为2的路径构成一个长度为6的不合法环。
所以像这种压边一般都是不靠谱的...
*/
Author: Fanfaredash