PAT1154 Vertex Coloring
数据量过大,但是边数不是很多,稀疏图,开邻接表存储边,注意使用set来记录使用的颜色数,PAT题目严格意义上涉及算法也不是很多。
#include<iostream>
#include<vector>
#include<unordered_set>
#define ac cin.tie(0);cin.sync_with_stdio(0);
using namespace std;
const int MAXN = 10010;
vector<int> G[MAXN];
int arr[MAXN];
int N, M, K;
int main() {
ac
int a, b;
cin >> N >> M;
while (M--) {
cin >> a >> b;
//存边
G[a].push_back(b);
G[b].push_back(a);
}
cin >> K;
while (K--) {
bool op = true;
//用来记录颜色数
unordered_set<int> set;
for (int i = 0; i < N; i++) {
cin >> arr[i];
if (!set.count(arr[i]))
set.insert(arr[i]);
}
for (int i = 0; i < N; i++)
for (int j:G[i])
//两个邻接点颜色相同,不符合
if (arr[i] == arr[j]) {
op = false;
break;
}
if (op)
cout << set.size() << "-coloring" << endl;
else
cout << "No" << endl;
}
return 0;
}
PAT1155 Heap Paths
由于是完全二叉树,满足2*k 为节点k的左儿子,2*k+1为节点k的右儿子,所以可以很方便的进行dfs遍历,同时要求先输出右边的路径,所以优先深度遍历右儿子,同时最后要求输出是最大还是最小堆,使用两个bool变量记录,如果有一个儿子比父结点大,就肯定不是大根堆,如果有一个儿子节点比父结点小,肯定就不是小根堆。
#include<iostream>
#define ac cin.tie(0);cin.sync_with_stdio(0);
using namespace std;
const int MAXN = 1010;
//arr为层序遍历 tmp为存储的临时路径 大小为log(MAXN)
int arr[MAXN], tmp[MAXN];
int n;
bool op1 = true, op2 = true;
void dfs(int root, int k) {
tmp[k++] = arr[root];
//优先深搜右节点
if (2 * root + 1 <= n)
dfs(2 * root + 1, k);
if (2 * root <= n)
dfs(2 * root, k);
//当前是叶子节点,需要输出路径
if (2 * root > n) {
for (int i = 0; i < k; i++) {
if (i) {
cout << " ";
if (tmp[i] > tmp[i - 1])
op1 = false;
if (tmp[i] < tmp[i - 1])
op2 = false;
}
cout << tmp[i];
}
cout << endl;
return;
}
}
int main() {
ac
cin >> n;
for (int i = 1; i <= n; i++)
cin >> arr[i];
dfs(1, 0);
if (op1)
cout << "Max Heap";
else if (op2)
cout << "Min Heap";
else
cout << "Not Heap";
return 0;
}
PAT1107 Social Clusters
并查集转换一下输入,根据爱好建立vector,vector[i]记录爱好为i的人的编号,然后对爱好i的所有人进行union操作即可。
#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
const int MAXN = 1010;
vector<int> G[MAXN], ans;
int pre[MAXN];
int n, m, a;
int find(int a) {
return a == pre[a] ? a : pre[a] = find(pre[a]);
}
//从大到小排序
bool cmp(int &a, int &b) {
return a > b;
}
int main() {
for (int i = 0; i < MAXN; i++)
pre[i] = i;
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
scanf("%d:", &m);
while (m--) {
scanf("%d", &a);
//建立邻接表
G[a].push_back(i);
}
}
for (int i = 1; i < MAXN; i++) {
//群体只有一个就不必并查集了
if (G[i].size() <= 1)
continue;
for (int j = 0; j < G[i].size() - 1; j++) {
int a = find(G[i][j]);
int b = find(G[i][j + 1]);
if (a != b)
pre[b] = a;
}
}
for (int i = 1; i <= n; i++) {
int tmp = find(i), cnt = 0;
//当前为新的群体
if (tmp == i) {
for (int j = 1; j <= n; j++)
if (find(j) == tmp)
//数量加一
++cnt;
ans.push_back(cnt);
}
}
printf("%d\n", ans.size());
//从大到小排序
sort(ans.begin(), ans.end(), cmp);
for (int i = 0; i < ans.size(); i++) {
if (i)
putchar(' ');
printf("%d", ans[i]);
}
return 0;
}
PAT1106 Lowest Price in Supply Chain
巩固不用Queue以及递归写宽搜,之后就是签到题了
#include<cstdio>
#include<vector>
using namespace std;
const int MAXN = 100010;
int arr[MAXN];
vector<int> G[MAXN];
int N;
double P, R;
int main() {
int len, a;
scanf("%d %lf %lf", &N, &P, &R);
for (int i = 0; i < N; i++) {
scanf("%d", &len);
while (len--) {
scanf("%d", &a);
G[i].push_back(a);
}
}
int tt = 0, hh = 0, size, cnt;
arr[0] = 0;
while (tt <= hh) {
if (tt)
P = P * (1 + 0.01 * R);
size = hh - tt + 1;
cnt = 0;
//size 为当前层的个数,模拟层序遍历
while (size--) {
int root = arr[tt++];
//找到根节点
if (G[root].size() == 0)
++cnt;
else
for (int i:G[root])
arr[++hh] = i;
}
//有根节点就break,找到了最浅的叶子节点
if (cnt)
break;
}
printf("%.4lf %d", P, cnt);
return 0;
}