week10

第一题 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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值