今天還是複習圖論。
一道最小生成樹的題目,題目其實不難。
但一開始邊的數目用的是MAXN*MAXN/2,MLE了一次,換vector之後不斷地WA……結果上來看是因爲沒有用素數篩法,之前用的是這樣的一個單獨判斷一個數是否是素數的辦法,也是之前一直用的,不知道爲什麼這次不行。
bool check(int x) {
if (x == 2 || x == 3) return true;
if (x % 6 != 5 && x % 6 != 1) return false;
for (int i = 5; i < sqrt(x); i += 6)
if (x % i == 0 || x % (i + 2) == 0) return false;
return true;
}
之後換用素數篩法之後就AC了……真是見鬼
#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <cstdlib>
#include <map>
#include <vector>
#include <queue>
#include <stack>
#include <set>
#include <list>
#include <cmath>
#include <algorithm>
#define MST(a, b) memset(a, b, sizeof(a))
using namespace std;
const int MAXN = 620;
const int MAXP = 2000000 + 50;
typedef long long ll;
struct edge {
int start, end, cur;
} ;
int t, n, value[MAXN], fa[MAXN];
bool prime[MAXP];
vector <edge> e;
void pre() {
MST(prime, 0);
prime[1] = 1;
for (int i = 2; i <= sqrt(MAXP); i++) {
if (prime[i]) continue;
for (int j = i * i; j < MAXP; j += i)
prime[j] = 1;
}
}
void init() {
for (int i = 1; i <= n; i++) fa[i] = i;
e.clear();
MST(value, 0);
}
int find_fa(int x) {
return fa[x] == x ? fa[x] : fa[x] = find_fa(fa[x]);
}
void merge_fa(int x, int y) {
int fx = find_fa(x), fy = find_fa(y);
if (fx != fy) fa[fy]= fx;
}
bool cmp(edge a, edge b) {
return a.cur < b.cur;
}
int kruskal() {
int res = 0, sum = 0;
sort(e.begin(), e.end(), cmp);
for (int i = 0; i < e.size(); i++) {
if (find_fa(e[i].start) != find_fa(e[i].end)) {
merge_fa(e[i].start, e[i].end);
res += e[i].cur;
sum++;
}
}
if (sum < n - 1) return -1;
return res;
}
int main() {
pre();
scanf("%d", &t);
while (t--) {
scanf("%d", &n);
init();
for (int i = 1; i <= n; i++) scanf("%d", &value[i]);
for (int i = 1; i <= n; i++)
for (int j = i + 1; j <= n; j++)
if (!prime[value[i]] || !prime[value[j]] || !prime[value[i] + value[j]]) {
edge tmpe;
tmpe.start = i;
tmpe.end = j;
tmpe.cur = min(min(value[i], value[j]), abs(value[i] - value[j]));
e.push_back(tmpe);
}
printf("%d\n", kruskal());
}
}