题目描述
知识点
图
实现
码前实现
- 这道题我写错了,我一开始是这样写的:
- 上面的分析确实有道理,如果一直两两点比较,那么就是组合数了,时间复杂度变成了 1 0 3 × 1 0 3 = 1 0 6 10^3 \times 10^3 = 10^6 103×103=106。但是,如果只是遍历边的话,那么最多也只有 2 × 1 0 4 2 \times 10^4 2×104的时间复杂度!
- 因此,每次都是扫描该点的所有不匹配点是否出现在了之前的数字中。
代码实现
#include "bits/stdc++.h"
using namespace std;
const int maxn = 1e5+10;
unordered_map<int,vector<int> > mp;
int n;
int m;
//用于标记是否在集合之中
bool vis[maxn];
int main(){
scanf("%d %d",&n,&m);
for(int i=0;i<n;i++){
int u;
int v;
scanf("%d %d",&u,&v);
mp[u].push_back(v);
mp[v].push_back(u);
}
for(int i=0;i<m;i++){
fill(vis,vis+maxn,false);
int k;
scanf("%d",&k);
//不使用全部输入
bool flag = true;
for(int j=0;j<k&&flag;j++){
int u;
scanf("%d",&u);
if(mp.count(u)){
for(int l=0;l<mp[u].size();l++){
int v = mp[u][l];
if(vis[v] == true){
flag = false;
break;
}
}
}
vis[u] = true;
}
string tmp;
getline(cin,tmp);
if(flag == true){
printf("Yes\n");
}else{
printf("No\n");
}
}
return 0;
}
码后反思
- 对于这种题,一定要看是针对点与点进行操作,还是针对边进行操作。他们的时间复杂度通常是不一样的。
- 很明显这里边的数量是少的,而点的数量是多的。相当于是一个稀疏图,那么使用边最好啊!!!就跟最小生成树一个思路啊!!!
二刷代码
我就是一头猪,怎么也教不会,这次又超时了,原因还是老原因,还是遍历所有物品判断了。。。
这次参考了柳神的代码:
#include <iostream>
#include <vector>
#include <map>
using namespace std;
int main(){
int n,k,t1,t2;
map<int,vector<int> > m;
scanf("%d%d",&n,&k);
for(int i=0;i<n;i++){
scanf("%d%d",&t1,&t2);
m[t1].push_back(t2);
m[t2].push_back(t1);
}
while(k--){
int cnt,flag=0,a[100000]={0};
scanf("%d",&cnt);
vector<int> v(cnt);
for(int i=0;i<cnt;i++){
scanf("%d",&v[i]);
a[v[i]] = 1;
}
for(int i=0;i<v.size();i++){
for(int j=0;j<m[v[i]].size();j++){
if(a[m[v[i]][j]] == 1) flag = 1;
}
}
printf("%s\n",flag?"No":"Yes");
}
return 0;
}