1134 Vertex Cover (25分)/图的特殊存储

题目描述

在这里插入图片描述
在这里插入图片描述

解析

我的思路是数边数——根据给定几个顶点,数出以这些顶点为端点的总边数,如果总边数与图的总边数相等,那么就满足条件。但是由于给出的顶点集合可能有相连的情况,需要去掉重复的边。但是这一步会将算法时间复杂度增加一个数量级,导致数据量大时运行超时。

#include<iostream>
#include<cstring>
#include<string>
#include<vector>
#include<map>
#include<set>
#include<unordered_set>
#include<stack>
#include<queue>
#include<cmath>
#include<algorithm>
using namespace std;
int adj[10005];
int G[10005][10005];
int main() {
#ifdef ONLINE_JUDGE
#else
	freopen("1.txt", "r", stdin);
#endif
	int n, m; cin >> n >> m;
	for(int i=0;i<m;i++) {
		int c1, c2;
		scanf("%d%d", &c1, &c2);
		adj[c1]++; adj[c2]++; //表示以顶点为边的个数
		G[c1][c2] = G[c2][c1] = 1;
	}
	int k; cin >> k;
	while (k--) {
		int num; cin >> num;
		unordered_set<int> sett;
		int chongfu = 0;
		while (num--) {
			int t; scanf("%d", &t);
			for (int i : sett) if (G[i][t] == 1) chongfu++; //计算会重复计算的边数
			sett.insert(t);
		}
		int cnt = 0;
		for (int id : sett) {
			cnt += adj[id];
		}
		cnt -= chongfu;
		printf("%s\n", cnt == m ? "Yes" : "No");
	}
	return 0;
}

看了柳神的代码,她是用了一种特殊的方式存储图:用编号标识每条边,边属于两端顶点。

#include<iostream>
#include<cstring>
#include<string>
#include<vector>
#include<map>
#include<set>
#include<unordered_set>
#include<stack>
#include<queue>
#include<cmath>
#include<algorithm>
using namespace std;
int main() {
#ifdef ONLINE_JUDGE
#else
	freopen("1.txt", "r", stdin);
#endif
	int n, m; scanf("%d%d", &n, &m);
	vector<vector<int>> v(n);
	for (int i = 0; i < m; i++) {
		int c1, c2;
		scanf("%d%d", &c1, &c2);
		v[c1].push_back(i);
		v[c2].push_back(i);
	}
	int k; cin >> k;
	while (k--) {
		int nv; scanf("%d", &nv);
		vector<bool> hash(m, 0);
		while (nv--) {
			int t; scanf("%d", &t);
			for (int i = 0; i < v[t].size(); i++) {
				hash[v[t][i]] = 1;
			}
		}
		int flag = 1;
		for (int i = 0; i < m; i++) {
			if (hash[i] == 0) {
				flag = 0; break;
			}
		}
		printf("%s\n", flag ? "Yes" : "No");
	}
	return 0;
}
发布了103 篇原创文章 · 获赞 9 · 访问量 4706

猜你喜欢

转载自blog.csdn.net/weixin_43590232/article/details/104370306