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