Southeastern European Regional Programming Contest Bucharest, Romania – Vinnytsya, Ukraine October 21, 2017
D - Harry Potter and The Vector Spell
题目链接:http://codeforces.com/gym/101669/attachments
解题心得:
- 题意说了很多,其实就是给你一个稀疏矩阵,矩阵中的值只有0或者1,矩阵的每一列有两个值为1的元素,现在需要你求这个矩阵的秩。
- 刚开始看到这个题队友叫了一声高斯消元,差点被带歪。其实就是一个并查集,先将矩阵行列置换,置换之后就成了每一行有两个1,然后对这个矩阵进行操作,其实看看样例就容易看出m行的矩阵秩最多为m-1,然后跟着推下就很容易看出建图的规律。
- 之后WA28, 然后发现坑点m行n列啊。
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5+100;
int father[maxn], n, m;
vector <int> ve[maxn];
void init() {
scanf("%d%d",&n,&m);
for(int i=1;i<maxn;i++) {
father[i] = i;
}
for(int i=1;i<=n;i++) {
int t; scanf("%d", &t);
while(t--) {
int temp; scanf("%d", &temp);
ve[temp].push_back(i);
}
}
}
int find(int x) {
if(father[x] == x) return x;
return father[x] = find(father[x]);
}
void merge(int x,int y) {
int fx = find(x);
int fy = find(y);
if(fx != fy) father[fx] = fy;
}
int ans = 0;
void kruskal() {
for(int i=1;i<=m;i++) {
int c1 = ve[i][0];
int c2 = ve[i][1];
if(find(c1) != find(c2)) {
ans++;
merge(c1, c2);
}
}
}
int main() {
//freopen("1.in", "r", stdin);
//freopen("1.out", "w", stdout);
init();
kruskal();
printf("%d", ans);
return 0;
}