PAT考前总复习
⛵️PAT总复习
这篇文章是关于一个PAT的总复习,整理以备复习参考。可能包含不全,我列出了一些易错点
🏖1.多项式
甲级1002.A+B for Polynomials
题,多项式中,个人认为,多项式用最快的方法就是map进行存储,然后进行依次打印。(1009.Product of Polynomials
,多项式乘法也可以用该方法做)
题意:给出2个多项式,输出和。模板案例如下:
#include <iostream>
#include <map>
using namespace std;
int main()
{
int M, coef, coun=2;
double expo;
map<int, double, greater<int>> m;
while(coun--){
cin >> M;
while(M--){
cin >> coef >> expo;
m[coef] += expo;
}
}
for(auto it = m.begin(); it != m.end(); it++)
if(it -> second == 0) m.erase(it);
cout << m.size();
for(auto it: m)
printf(" %d %.1f", it.first, it.second);
return 0;
}
🏝2.素数
素数考察主要是素数判别,可能会加上一些其他基础逻辑。参考1015.Reversible Primes
, 1152.Google Recruitment
素数的判别写法如下:
bool isPrime(int N){
if(N <= 1) return false;
for(int i = 2; i * i <= N; i++)
if(N % i ==0) return false;
return true;
}
🏜3.Java优先题型
大数字题型
大数字,考试就不要想***钻的方法了,平时练习可以考虑cpp如何处理,也不要想范围,就直接用Java语言进行处理。
如:1065 a+b(64 bit)
import java.math.BigInteger;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int N = sc.nextInt();
BigInteger A, B, C;
for(int i = 1; i <= N; i++) {
A = sc.nextBigInteger();
B = sc.nextBigInteger();
C = sc.nextBigInteger();
if(A.add(B).compareTo(C)>0)
System.out.printf("Case #%d: true\n", i);
else
System.out.printf("Case #%d: false\n", i);
}
}
}
一眼看上去就很方便的题型
如:1024.Palindromic Number
import java.math.BigInteger;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
BigInteger b = sc.nextBigInteger();
int cnt = sc.nextInt(), i;
for(i = 0; i < cnt; i++)
if(b.toString().equals(new StringBuilder(b.toString()).reverse().toString())) break;
else b = new BigInteger(new StringBuilder(b.toString()).reverse().toString()).add(b);
System.out.println(b + "\n" + i);
}
}
⛳︎4.链表Vector模拟
反转链表往往用struct node{} 会比较浪费脑力,如果遇到了,统一使用unodered_map
进行寻址,如:1074.Reversing Linked List
#include "iostream"
#include "vector"
#include "map"
using namespace std;
// 使用一个三元组node进行存储元素
struct node {
int val, addr, next;
}tmp;
// 一定要方便逻辑处理,一般不会超空间,可以多遍历几次筛选
vector<node> v, tmp_v, ans;
// 这题使用map不会超时,如果超时,使用unordered_map
map<int, node> m;
int main() {
int start, N, K;
scanf("%d%d%d", &start, &N, &K);
for(int i = 0; i < N; i++) { // 读数
scanf("%d%d%d", &tmp.addr, &tmp.val, &tmp.next);
m[tmp.addr] = tmp;
}
while(start != -1) { // 顺序化链表
v.push_back(m[start]);
start = m[start].next;
}
for(int i = 0; i < v.size(); i++) {
tmp_v.push_back(v[i]);
if(tmp_v.size() == K) { // k个反转
for(int j = tmp_v.size() - 1; j >= 0; j--)
ans.push_back(tmp_v[j]);
tmp_v.clear();
}
}
for(int i = 0; i < tmp_v.size(); i++)
ans.push_back(tmp_v[i]); // 剩余顺序放入
for(int i = 0; i < ans.size(); i++) // 打印
if(i == 0) printf("%05d %d", ans[i].addr, ans[i].val);
else printf(" %05d\n%05d %d", ans[i].addr, ans[i].addr, ans[i].val);
if(ans.size() != 0) printf(" -1");
return 0;
}
⛽︎5.精度问题
例如1070.Mooncake
,需要进行精度计算的题目,我们统一把所有变量都定义为double,一般情况能过。(如果还是精度不够,可以尝试将数字扩大1000倍,进行计算后,最后再统一除以1000。如果不想思考了,可以尝试使用Java的BigDecimal,那个更为精准)
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
// 这边变量定义为double
struct mooncake {
double cnt, price;
};
vector<mooncake> v;
bool cmp(mooncake mc, mooncake mc2) {
return mc.price * mc2.cnt < mc2.price * mc.cnt;
}
int main() {
// 考试很紧张,遇到精度题,所有都定义为double吧。嘿嘿,不要思考啦。
double N, target;
scanf("%lf %lf", &N, &target);
v.resize(N);
for(int i = 0; i < N; i++)
scanf("%lf", &v[i].price);
for(int i = 0; i < N; i++)
scanf("%lf", &v[i].cnt);
sort(v.begin(), v.end(), cmp);
double ans = 0;
for(int i = 0; i < N && target != 0; i++){
if(v[i].price <= target){
target -= v[i].price;
ans += v[i].cnt;
}else {
ans += (target * v[i].cnt / v[i].price);
target = 0;
}
}
printf("%.2f", ans);
return 0;
}
⛺︎6.大规模计数
如:1093. Count PATs
,整个题库中仅有的1题,印象深刻,我们需要用到一组串中的前后进行累乘的,可以通过1次遍历进行计算总数,然后第二次遍历,进行前加后减的方法进行。
这里提到的第一点是前加后减的方法(虽然再遇到可能性不大),但是我们记得在每步运算都加上 %1000000007
#include <iostream>
using namespace std;
int main()
{
string s;
getline(cin, s);
long long P = 0, A = 0, T = 0, sum = 0;
for(int i = 0; i < s.length(); i++)
if(s[i] == 'T') T++;
for(int i = 0; i < s.length(); i++){
if(s[i] == 'P') P++;
if(s[i] == 'T') T--;
if(s[i] == 'A') sum += ((P % 1000000007 * T % 1000000007) % 1000000007);
}
cout << sum % 1000000007;
return 0;
}
⛲7.最大公因数
最大公因数的模板如下,当n2为0的时候,返回n1,否则返回递归gcd(n2, n1 % n2)
。
/** 最大公约数 */
long long gcd(long long n1, long long n2) {
return n2 == 0 ? n1 : gcd(n2, n1 % n2);
}
除了这个方法,介绍一个很方便的内置函数。
在windows和linux下的<algorithm>
中含有一个内置函数,__gcd(x, y)
,我们仅仅需要使用这个内置函数即可完成gcd,但是这个函数在mac下不支持。
#include <algorithm>
cout << __gcd(3, 6); // 直接使用内置函数
⛪︎8.螺旋矩阵
螺旋矩阵,我们通过一个设计模式书上的案例即可达到。我们定义一个方向变量dir,进行模拟旋转方向,然后每次移动一次move()
,1105.Spiral Matrix
代码如下:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int N;
int main() {
scanf("%d", &N);
vector<int> v(N);
for(int i = 0; i < N; i++)
scanf("%d", &v[i]);
sort(v.begin(), v.end(), greater<int>());
int col, row;
for(int i = 1; i * i <= N; i++)
if(N % i == 0) col = i;
row = N / col;
vector<vector<int>> ans(row);
for(int i = 0; i < row; i++) ans[i].resize(col, -1);
int x = 0, y = 0, dir = 0, i = 0;// 0 右边 1 下面 2 左面 3 上面
if(y + 1 >= col || ans[x][y + 1] != -1) dir = (dir + 1) % 4; // 开始方向可能朝下
while(true) {
if(i == v.size()) break;
if(dir == 0) {
ans[x][y++] = v[i++];
if(y + 1 >= col || ans[x][y + 1] != -1) dir = (dir + 1) % 4;
} else if(dir == 1) {
ans[x++][y] = v[i++];
if(x + 1 >= row || ans[x + 1][y] != -1) dir = (dir + 1) % 4;
} else if(dir == 2) {
ans[x][y--] = v[i++];
if(y - 1 < 0 || ans[x][y - 1] != -1) dir = (dir + 1) % 4;
} else {
ans[x--][y] = v[i++];
if(x - 1 < 0 || ans[x - 1][y] != -1) dir = (dir + 1) % 4;
}
}
for(int i = 0; i < row; i++) {
printf("%d", ans[i][0]);
for(int j = 1; j < col; j++)
printf(" %d", ans[i][j]);
putchar('\n');
}
return 0;
}
⛄︎9.暴力递归
写递归题需要注意,在去年9月真题的第一题15分的forever
,就要求写暴力递归。后来我在题库中也找到一题需要写暴力递归的。
暴力递归的主要核心是:
- 1.进行拆解条件,我们选择脑海中觉得复杂度最低的条件,进行构建函数,进行暴力递归。
- 2.剪枝,剪枝也就是所谓的写循环出口,我们可以写一些没必要的条件中立马让递归进行
return
,这样能够打打降低算法的复杂度。
下题为题库的1103.Integer Factorization
#include <iostream>
#include <cmath>
#include <vector>
using namespace std;
int N, K, P, maxFacSum = -1;
vector<int> v, ans, tmpAns;
void init() {
int tmp = 0, index = 1;
while(tmp <= N) {
v.push_back(tmp);
tmp = pow(index++, P);
}
}
void dfs(int index, int tmpSum, int tmpK, int facSum) {
if(tmpK == K) {
if(tmpSum == N && facSum > maxFacSum) {
ans = tmpAns;
maxFacSum = facSum;
}
return;
}
while(index >= 1) {
if(tmpSum + v[index] <= N) {
tmpAns[tmpK] = index;
dfs(index, tmpSum + v[index], tmpK + 1, facSum + index);
}
if(index == 1) return;
index--;
}
}
int main() {
scanf("%d%d%d", &N, &K, &P);
init();
tmpAns.resize(K);
dfs(v.size() - 1, 0, 0, 0);
if(maxFacSum == -1) printf("Impossible");
else {
printf("%d = ", N);
for(int i = 0; i < ans.size(); i++) {
if(i != 0) printf(" + ");
printf("%d^%d", ans[i], P);
}
}
return 0;
}
⭐︎10.Hashing
虽然有线性探测 和 平方探测,不变的点是查找要多查一次。
线性探测法,参考Data Structures and Algorithms(English)
7-18 Hashing - Hard Version(30')
#include <iostream>
#include <vector>
#include <map>
#include <set>
using namespace std;
map<int, set<int>> G;
map<int, int> degree;
int main() {
int N, tmp, cnt = 0;
scanf("%d", &N);
vector<int> v(N), ans;
for(int i = 0; i < N; i++) {
scanf("%d", &v[i]);
if(v[i] > 0) {
degree[v[i]] = 0; // 入度设置为0
cnt++;
}
}
for(int i = 0; i < N; i++) {
if(v[i] > 0) {
int tmp = v[i];
while(tmp % N != i) {
G[v[tmp % N]].insert(v[i]);
tmp++;
degree[v[i]]++;
}
}
}
int index = 0;
while(index != cnt) {
int min;
for(auto x: degree) {
if(x.second == 0) {
min = x.first;
break;
}
}
degree[min]--;
for(auto x: G[min]) degree[x]--;
ans.push_back(min);
index++;
}
printf("%d", ans[0]);
for(int i = 1; i < cnt; i++)
printf(" %d", ans[i]);
return 0;
}
平方探测法,参考 1145 Hashing - Average Search Time
#include <iostream>
#include <vector>
using namespace std;
bool isPrime(int N) {
if(N <= 1) return false;
for(int i = 2; i * i <= N; i++)
if(N % i == 0) return false;
return true;
}
int main() {
int MSize, N, M, tmp;
cin >> MSize >> N >> M;
while(!isPrime(MSize)) MSize++;
vector<int> hash(MSize, 0);
while(N--) {
cin >> tmp;
int flag = true;
for(int i = 0; i < MSize; i++) {
if(hash[(tmp + i * i) % MSize] == 0) {
hash[(tmp + i * i) % MSize] = tmp;
flag = false;
break;
}
}
if(flag) printf("%d cannot be inserted.\n", tmp);
}
int cnt = 0;
for(int c = 0; c < M; c++) {
cin >> tmp;
for(int i = 0; i <= MSize; i++) {
cnt++;
if(hash[(tmp + i * i) % MSize] == tmp ||
hash[(tmp + i * i) % MSize] == 0)
break;
}
}
printf("%.1lf", (double)cnt / M);
return 0;
}
⛅︎11.二叉树中序遍历
参考 1064. Complete Binary Search Tree
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int N, index_v = 0 ;
vector<int> v, res;
void inorder(int index_res){
if(index_res >= N) return;
inorder(2 * index_res + 1);
res[index_res] = v[index_v++];
inorder(2 * index_res + 2);
}
int main(){
cin >> N;
v.resize(N);
res.resize(N);
for(int i = 0; i < N; i++)
cin >> v[i];
sort(v.begin(),v.end());
inorder(0);
cout << res[0];
for(int i = 1; i < N; i++)
cout << " " << res[i];
return 0;
}
🧆12.AVL模板
参照1066. Root of AVL Tree
,记忆一遍,实在不行,找中位数,也能拿到大半分。
#include "iostream"
using namespace std;
struct node {
int val;
node *left, *right;
node(int v):val(v), left(NULL), right(NULL) {}
} *root;
// get height
int get_height(node* root) {
if(!root) return 0;
return max(get_height(root->left), get_height(root->right)) + 1;
}
// Single Left Rotation
node* single_left_rotation(node* root) {
node* tmp = root->left;
root->left = tmp->right;
tmp->right = root;
return tmp;
}
// Single Right Rotation
node* single_right_rotation(node* root) {
node* tmp = root->right;
root->right = tmp->left;
tmp->left = root;
return tmp;
}
// Double Left Right Rotation
node* double_left_right_rotation(node* root) {
root->left = single_right_rotation(root->left);
return single_left_rotation(root);
}
// Double Right left Rotation
node* double_right_left_rotation(node* root) {
root->right = single_left_rotation(root->right);
return single_right_rotation(root);
}
// insert
node* insert(node* root, int data) {
if(root == NULL) root = new node(data);
else if(data < root->val) {
root->left = insert(root->left, data);
if(get_height(root->left) - get_height(root->right) == 2) {
if(data < root->left->val) root = single_left_rotation(root);
else root = double_left_right_rotation(root);
}
} else {
root->right = insert(root->right, data);
if(get_height(root->right) - get_height(root->left) == 2) {
if(data > root->right->val) root = single_right_rotation(root);
else root = double_right_left_rotation(root);
}
}
return root;
}
int main() {
int N, tmp;
scanf("%d", &N);
while(N--) {
scanf("%d", &tmp);
root = insert(root, tmp);
}
printf("%d", root->val);
return 0;
}
🥝13.建树问题
前中建树:
void pre(int root, int start, int end) {
if(start > end) return ;
int i = start;
while(i < end && in[i] != post[root]) i++;
printf("%d ", post[root]);
pre(root - 1 - end + i, start, i - 1);
pre(root - 1, i + 1, end);
}
后中建树:
void post(int root, int start, int end) {
if(start > end)
return ;
int i = start;
while(i < end && in[i] != pre[root]) i++;
post(root + 1, start, i - 1);
post(root + 1 + i - start, i + 1, end);
printf("%d ", pre[root]);
}
层中建树:
node* build(int level_left, int level_right, int in_left, int in_right) {
if(in_left > in_right) return NULL;
int k, flag = 0;
while(level_left <= level_right) {
for(k = in_left; k <= in_right; k++)
if(in[k] == level[level_left]) {
flag = 1;
break;
}
if(flag) break;
level_left++;
}
node *n = new node(in[k]);
n->left = build(level_left + 1, level_right, in_left, k - 1);
n->right = build(level_left + 1, level_right, k + 1, in_right);
return n;
}
先后建树(其中一种):
node *build(int pre_l, int pre_r, int post_l, int post_r) {
if(pre_l > pre_r) return NULL;
if(pre_l == pre_r) return new node(pre[pre_l]);
node *n = new node(pre[pre_l]);
int k = post_l;
while(k < post_r && post[k] != pre[pre_l + 1]) k++;
n->left = build(pre_l + 1, pre_l + 1 + k - post_l, post_l , k - 1);
n->right = build(pre_l + 1 + k - post_l + 1, pre_r, k + 1, post_r - 1);
return n;
}
🍑14.层序遍历
建树和层序遍历和中序遍历,都在1099 Build A Binary Search Tree
#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;
struct node {
int data, left, right;
}tree[99999];
int ele[99999], N, l, r, ele_i = 0, start = true;
void inorder(int root) {
if(tree[root].left != -1) inorder(tree[root].left);
tree[root].data = ele[ele_i++];
if(tree[root].right != -1) inorder(tree[root].right);
}
void levelorder(int root) {
queue<int> que;
que.push(root);
while(!que.empty()) {
node n = tree[que.front()];
if(start) printf("%d", n.data);
else printf(" %d", n.data);
start = false;
que.pop();
if(n.left != -1) que.push(n.left);
if(n.right != -1) que.push(n.right);
}
}
int main() {
scanf("%d", &N);
for(int i = 0; i < N; i++) scanf("%d%d", &tree[i].left, &tree[i].right);
for(int i = 0; i < N; i++) scanf("%d", &ele[i]);
sort(ele, ele + N);
inorder(0);
levelorder(0);
return 0;
}
🏠15.反转二叉树
只要输入的时候,反着输入即可。参考1102 Invert a Binary Tree
#include "iostream"
#include "vector"
#include "string"
#include "queue"
using namespace std;
int N;
string tmp_l, tmp_r;
struct node {
int data, left = -1, right = -1, level;
};
vector<node> v;
void levelorder(int root) {
bool start = true;
queue<node> que;
que.push(v[root]);
while(!que.empty()) {
node n = que.front();
if(start) {
printf("%d", n.data);
start = false;
} else printf(" %d", n.data);
que.pop();
if(n.left != -1) que.push(v[n.left]);
if(n.right != -1) que.push(v[n.right]);
}
}
bool start = true;
void inorder(int root) {
if(v[root].left != -1) inorder(v[root].left);
if(start) {
start = !start;
printf("%d", v[root].data);
} else printf(" %d", v[root].data);
if(v[root].right != -1) inorder(v[root].right);
}
int main() {
scanf("%d", &N);
v.resize(N);
vector<bool> judge(N, false);
for(int i = 0;i < N; i++) {
cin >> tmp_l >> tmp_r;
v[i].data = i;
if(tmp_l != "-") {
v[i].right = stoi(tmp_l);
judge[stoi(tmp_l)] = true;
}
if(tmp_r != "-") {
v[i].left = stoi(tmp_r);
judge[stoi(tmp_r)] = true;
}
}
int root_index;
for(int i = 0; i < N; i++)
if(judge[i] == false) root_index = i;
levelorder(root_index);
putchar('\n');
inorder(root_index);
return 0;
}
🏡16.完全二叉树
完全二叉树的判定就是:层序遍历,出现间断则不是完全二叉树。
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
struct node {
int v;
string left, right;
}n[30];
int N, root = 0, last;
bool isComplete(int root) {
queue<int> que;
que.push(root);
bool flag = 1, ret = true;
while(!que.empty()) {
node tmp = n[que.front()];
que.pop();
last = tmp.v;
if(tmp.left != "-") que.push(stoi(tmp.left));
if(tmp.right != "-") que.push(stoi(tmp.right));
if(flag) {
if(tmp.left != "-" && tmp.right != "-") {
} else if(tmp.left != "-") {
flag = 0;
} else if(tmp.right != "-") {
ret = false;
} else {
flag = 0;
}
} else {
if(tmp.left != "-" || tmp.right != "-") ret = false;
}
}
return ret;
}
int main() {
cin >> N;
vector<int> find_root(N, 0);
for(int i = 0; i < N; i++) {
n[i].v = i;
cin >> n[i].left >> n[i].right;
if(n[i].left != "-") find_root[stoi(n[i].left)] = 1;
if(n[i].right != "-") find_root[stoi(n[i].right)] = 1;
}
while(root < N && find_root[root]) root++;
bool complete = isComplete(root);
printf("%s %d\n", complete ? "YES": "NO", complete ? last: root);
return 0;
}
🏘17.lca算法
lca的算法是进行写递归,分为2个算法。
// lca_bst
node *lca_bst(node *n, node *p, node *q) {
if((n->val - p->val) * (n->val - q->val) <= 0) return n;
else if(n->val < p->val && n->val < q->val) return lca_bst(n->right, p, q);
else return lca_bst(n->left, p ,q);
}
// lca_common
node* lca_common(node *n, node *p, node *q) {
if (n == NULL) return NULL;
if (n->val == p->val || n->val == q->val) return n;
node *left = lca_common(n->left, p, q);
node *right = lca_common(n->right, p, q);
if (left != NULL && right != NULL) return n;
if (left != NULL) return left;
if (right != NULL) return right;
return NULL;
}
🐶18.Dijkstra模板
Dijkstra
#include <iostream>
#include <algorithm>
using namespace std;
int n, m, c1, c2;
int edge[510][510], weight[510], dis[510], num[510], w[510];
bool vis[510];
const int inf = 99999999;
int main() {
scanf("%d%d%d%d", &n, &m, &c1, &c2);
for(int i = 0; i < n; i++)
scanf("%d", &weight[i]);
fill(edge[0], edge[0] + 510 * 510, inf);
fill(dis, dis + 510, inf);
int a, b, c;
for(int i = 0; i < m; i++){
scanf("%d%d%d", &a, &b, &c);
edge[a][b] = edge[b][a] = c;
}
dis[c1] = 0;
w[c1] = weight[c1];
num[c1] = 1;
while(true) {
int u = -1, minn = inf;
for(int j = 0; j < n; j++){
if(vis[j] == false && dis[j] < minn) {
u = j;
minn = dis[j];
}
}
if(u == -1) break;
vis[u] = true;
for(int v = 0; v < n; v++) {
if(vis[v] == false && edge[u][v] != inf) {
if(dis[u] + edge[u][v] < dis[v]) {
dis[v] = dis[u] + edge[u][v];
num[v] = num[u];
w[v] = w[u] + weight[v];
}else if(dis[u] + edge[u][v] == dis[v]) {
num[v] = num[v] + num[u];
if(w[u] + weight[v] > w[v])
w[v] = w[u] + weight[v];
}
}
}
}
printf("%d %d", num[c2], w[c2]);
return 0;
}
Dijkstra堆优化
#include <iostream>
#include <queue>
#include <algorithm>
using namespace std;
int n, m, c1, c2;
int edge[510][510], weight[510], dis[510], num[510], w[510];
bool vis[510];
const int inf = 99999999;
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> q;
int main() {
scanf("%d%d%d%d", &n, &m, &c1, &c2);
for(int i = 0; i < n; i++)
scanf("%d", &weight[i]);
fill(edge[0], edge[0] + 510 * 510, inf);
fill(dis, dis + 510, inf);
int a, b, c;
for(int i = 0; i < m; i++){
scanf("%d%d%d", &a, &b, &c);
edge[a][b] = edge[b][a] = c;
}
dis[c1] = 0;
w[c1] = weight[c1];
num[c1] = 1;
q.push({0, c1});
while(q.size()) {
// 改为了弹出
int u = q.top().second;
q.pop();
// 如果已经访问,这边记得进行continue操作
if(vis[u]) continue;
vis[u] = true;
for(int v = 0; v < n; v++) {
if(vis[v] == false && edge[u][v] != inf) {
if(dis[u] + edge[u][v] < dis[v]) {
dis[v] = dis[u] + edge[u][v];
num[v] = num[u];
w[v] = w[u] + weight[v];
}else if(dis[u] + edge[u][v] == dis[v]) {
num[v] = num[v] + num[u];
if(w[u] + weight[v] > w[v])
w[v] = w[u] + weight[v];
}
q.push({dis[v], v});
}
}
}
printf("%d %d", num[c2], w[c2]);
return 0;
}
Bellman-Ford把普通Dijstra其中的贪心思想换成2重遍历即可,SPFA把Bellman-Ford进行堆优化即可。
Floyd算法:多源短路问题
void Floyd(){
for(k = 0; k < N; k++)
for(i = 0; i < N; i++)
for(j = 0; j < N; j++)
if(D[i][k] + D[k][j] < D[i][j]) {
D[i][j] = D[i][k] + D[k][j];
path[i][j] = k;
}
}
🛕19.Prim&Kruskal
参照数据结构题集7-11
Prim:
#include <iostream>
#include <queue>
#include <vector>
#define INF 999999
using namespace std;
int N, M, a, b, c;
int e[1010][1010] = {0}, dist[1010], vis[1010] = {0};
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> q;
int main() {
scanf("%d%d", &N, &M);
while(M--) {
scanf("%d%d%d", &a, &b, &c);
e[a][b] = e[b][a] = c;
}
fill(dist, dist + 1010, INF);
dist[1] = 0;
q.push({0, 1});
while(q.size()) {
int u = q.top().second;
q.pop();
if(vis[u]) continue;
vis[u] = 1;
for(int v = 1; v <= N; v++) {
if(!vis[v] && e[u][v] && dist[v] > e[u][v]) {
dist[v] = e[u][v];
q.push({dist[v], v});
}
}
}
int sum = 0, conn = 1;
for(int i = 1; i <= N; i++) {
sum += dist[i];
if(!vis[i]) conn = 0;
}
if(!conn) printf("-1\n");
else printf("%d\n", sum);
return 0;
}
Kruskal:
#include <iostream>
#include <queue>
#include <vector>
#define INF 999999
using namespace std;
int N, M, a, b, c;
int vis[1010] = {0};
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> q;
int main() {
scanf("%d%d", &N, &M);
while(M--) {
scanf("%d%d%d", &a, &b, &c);
q.push({c, a * 10000 + b});
}
int sum = 0, conn = 1;
while(q.size()) {
int m = q.top().second / 10000;
int n = q.top().second % 10000;
if(!vis[m] || !vis[n]) {
sum += q.top().first;
vis[m] = vis[n] = 1;
}
q.pop();
}
printf("%d\n", sum);
return 0;
}