https://codeforces.com/contest/1198/problem/C
要选取一个大小大于等于n的匹配或者选取一个大小大于等于n的独立集。
考虑不断加入匹配集,最终加入了x条边。
那么剩下的点之间是没有边可以加的,否则匹配数还会增加,也就是剩下的点要么没有边可以连,要么这些边去往的点都在匹配里面。
考虑x>=n,之间输出。
否则x<n,则剩下的点至少有3n-2x个,这些全部选上也>=n,连匹配里面的点都不需要动(因为匹配里面的点可能会和匹配外的点有边连通)。
其实看见有3*n个点应该反应到是要为什么这样搞的。
#include<bits/stdc++.h>
using namespace std;
bool vis[300005];
int eid[500005], etop;
void init(int n, int m) {
memset(vis, 0, sizeof(vis[0]) * (3*n + 1));
etop = 0;
}
void update(int i) {
int u, v;
scanf("%d%d", &u, &v);
if(vis[u] || vis[v])
return;
else {
vis[u] = vis[v] = 1;
eid[++etop] = i;
}
}
void Matching(int n) {
puts("Matching");
for(int i = 1; i <= n; ++i) {
printf("%d%c", eid[i], "
"[i == n]);
}
}
void IndSet(int n) {
puts("IndSet");
int cnt = 0;
for(int i = 1; i <= 3 * n; ++i) {
if(!vis[i]) {
++cnt;
printf("%d%c", i, "
"[cnt == n]);
if(cnt == n)
return;
}
}
}
int main() {
#ifdef Yinku
freopen("Yinku.in", "r", stdin);
#endif // Yinku
int T;
scanf("%d", &T);
int n, m;
while(T--) {
scanf("%d%d", &n, &m);
init(n, m);
for(int i = 1; i <= m; ++i) {
update(i);
}
if(etop >= n) {
Matching(n);
} else {
IndSet(n);
}
}
}
以前没怎么接触过什么匹配、独立集,不会做才正常。