第一题 P1636 Einstein学画画
原理,欧拉图
1.一条边有两个点,要想经过所有边,则所有点都要进一次出一次,除了起点和终点,若起点和终点也为偶数,就是回路了。
2.一个联通图只可能有偶数个奇点。假设原来是一个全偶点的图,每给他加一个奇点,因为一条边连两点,比会加两个奇点。
#include <bits/stdc++.h>
using namespace std;
int n, m;
int map1[1010];
int main() {
cin >> n >> m;
for (int i = 0; i < m; i++) {
int s, e;
cin >> s >> e;
map1[s]++;
map1[e]++;
}
int fei = 0;
for (int i = 1; i <= n; i++) {
if (map1[i] % 2 != 0)fei++;
}
cout << (fei / 2<=1 ? 1 : fei / 2);
}
第二题 P8654 [蓝桥杯 2017 国 C] 合根植物
每一个树dfs一边,这题,是不是再哪写过。。
#include <bits/stdc++.h>
using namespace std;
int n, m;
int again[10000010];
vector <int> map1[10000010];
void dfs(int x) {
if (again[x])return;
again[x] = 1;
for (int i = 0; i < map1[x].size(); i++) {
dfs(map1[x][i]);
}
}
int main() {
cin >> m >> n;
int k;
cin >> k;
for (int i = 0; i < k; i++) {
int s, e;
cin >> s >> e;
map1[s].push_back(e);
map1[e].push_back(s);
}
int num = 0;
for (int i = 1; i <= n*m; i++) {
if (again[i])continue;
num++;
dfs(i);
}
cout << num;
}
P3958 [NOIP2017 提高组] 奶酪
最开始想的是对所有点分类归类,但后面发现,分好的两个集合可能因为一个点连在一起,我原先的分类方法处理不了,于是,上了并查集,归类的地方我觉得还能再缩短,也许不用每个点都遍历一遍,不过那样,可能得改map1的数据结构?搜索部分我先记录了哪些点碰顶,触底,由这些点来搜次数少点。
#define _CRT_SECURE_NO_WARNINGS
#include <bits/stdc++.h>
using namespace std;
struct hole {
double x, y, z;
};
double ju(double x1, double x2, double y1, double y2, double z1, double z2) {
return sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2) + (z1 - z2) * (z1 - z2));
};
int pre[10010];
int find(int x) {
if (pre[x] == x)return x;
return pre[x] = find(pre[x]);
}
void join(int x,int y) {
int fx = find(x), fy = find(y);
if (fx != fy)pre[fx] = fy;
}
int main() {
//freopen("P3958_5.in.txt", "r", stdin);
int t;
cin >> t;
for (int q = 0; q < t; q++) {
int n;
double h, r;
cin >> n >> h >> r;
vector <hole> map1;
vector<int> maxh;
vector <int>minh;
for (int i = 0; i < n; i++) {
double x, y, z;
cin >> x >> y >> z;
if (z - r <= 0)minh.push_back(i);
if (z + r >= h)maxh.push_back(i);
pre[i] = i;
map1.push_back({ x,y,z });
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < i; j++) {
if (ju(map1[i].x, map1[j].x, map1[i].y, map1[j].y, map1[i].z, map1[j].z) <= 2*r) {
join(i, j);
}
}
}
for (int i = 0; i < maxh.size(); i++) {
for (int j = 0; j < minh.size(); j++) {
if (find(maxh[i]) == find(minh[j])) {
cout << "Yes" << endl;
goto end;
}
}
}
cout << "No" << endl;
end:;
}
}
第四题 P1119 灾后重建
dijkstra加了一个起和终判断写的
#define _CRT_SECURE_NO_WARNINGS
#include <bits/stdc++.h>
using namespace std;
int n, m;
struct edge
{
int end, len;
};
int t[300];
vector <edge> map1[300];
int dis[300];
struct cmp
{
bool operator ()(const edge a, const edge b) {
return a.len > b.len;
}
};
int main() {
cin >> n >> m;
for (int i = 0; i < n; i++) {
int t1;
cin >> t1;
t[i] = t1;
}
for (int i = 0; i < m; i++) {
int s, e, l;
cin >> s >> e >> l;
map1[s].push_back({ e,l });
map1[e].push_back({ s,l });
}
int turn;
int again[300];
cin >> turn;
while (turn--) {
memset(dis, 0x3f3f3f3f, sizeof(dis));
int s, e, ts;
cin >> s >> e >> ts;
memset(again, 0, sizeof(again));
priority_queue <edge, vector <edge>, cmp> dui;
dis[s] = 0;
dui.push({ s,dis[s] });
while (!dui.empty()) {
int en = dui.top().end;
int le = dui.top().len;
dui.pop();
if (le != dis[en])continue;
if (t[en] - ts > 0)continue;
again[en] = 1;
for (int i = 0; i < map1[en].size(); i++) {
if (t[map1[en][i].end] - ts > 0) {
continue;
}
if (again[map1[en][i].end])continue;
if (dis[en] + map1[en][i].len < dis[map1[en][i].end]) {
dis[map1[en][i].end] = dis[en] + map1[en][i].len;
dui.push({ map1[en][i].end,dis[map1[en][i].end] });
}
}
}
if (dis[e] == 0x3f3f3f3f) {
cout << -1 << endl;
}
else {
cout << dis[e]<<endl;
}
}
}
P2504 [HAOI2006]聪明的猴子
用了并查集和Kruskal算法,
1.按照边的权值将边进行升序排序,然后从小到大一一判断
2.如果这个边与之前选择的所有边不会组成回路,就选择这条边,反之舍去
3.不断判断,直到具有n个顶点的联通网筛选出来n-1条边为止。
#include <bits/stdc++.h>
using namespace std;
int pre[1010];
int find(int x) {
if (pre[x] == x)return x;
return pre[x] = find(pre[x]);
}
struct node
{
int s, e;
double len;
};
vector <node> map1;
double map2[1010][2];
bool cmp(node a,node b) {
return a.len < b.len;
}
int main() {
int n, m;
double mo[1010];
cin >> m;
for (int i = 1; i <= m; i++) {
cin >> mo[i];
}
cin >> n;
for (int i = 1; i <= n; i++) {
pre[i] = i;
int x, y;
cin >> x >> y;
map2[i][0] = x, map2[i][1] = y;
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
if (i == j)continue;
map1.push_back({ i,j,sqrt((map2[i][0] - map2[j][0]) * (map2[i][0] - map2[j][0]) + (map2[i][1] - map2[j][1]) * (map2[i][1] - map2[j][1])) });
}
}
sort(map1.begin(),map1.end(),cmp);
double maxn = 0;
int temp = n;
for(int i=0;i<map1.size();i++)
{
if (temp == 1)break;
int s = map1[i].s;
int e = map1[i].e;
double len = map1[i].len;
if (find(s) != find(e)) {
pre[find(s)] = find(e);
maxn = len;
temp--;
}
}
int num = 0;
for (int i = 1; i <= m; i++) {
if (mo[i] >= maxn)num++;
}
cout << num;
}