Harry Potter and The Vector Spell-gym101669D(矩阵的秩-并查集)

在这里插入图片描述
Sample Input

3 3 
2 1 3 
2 1 2 
2 2 3 

Sample Output
2
Sample Input 2

4 3
3 1 2 3 
1 1
1 2
1 3

在这里插入图片描述

Sample Output 2
3
题意:
给出一个0 1矩阵,这个矩阵中每一列有且只有两个1,求这个矩阵的秩
输入一行中1的数量x,然后后面x个数代表1出现的列位置
求出这个矩阵的秩

方法:
思维并查集
将每一列的两个1所在的行编号连一条边,然后求一下最小生成树就好
其实就是我们维护一个并查集,在这个并查集里面的所有点都可以两两组合形成一列,如果不在同一个集合里面,就会对答案+1

int fa[maxn];
int vis[maxn];
int n,m;
inline void init(){
    for(int i=0;i<maxn;i++) fa[i] = i,vis[i] = 0;
}
inline int findFa(int x){
    if(x == fa[x]) return x;
    else return fa[x] = findFa(fa[x]);
}
int ans = 0;
inline void Union(int x,int y){
    int fax = findFa(x);
    int fay = findFa(y);
    if(fax == fay) return ;
    else{
        fa[fax] = fay;
        ans ++;
    }
}
vector<int> vet[maxn];
int main() {
    cin >> m >> n;
    init();
    for(int i=1;i<=m;i++){
        int x=read;
        while(x --){
            int val; cin >>val;
            vet[val].push_back(i);
        }
    }

    for(int i=1;i<=n;i++){
        int x = vet[i][0];
        int y = vet[i][1];
        Union(x,y);
    }
    cout << ans << endl;
	return 0;
}
int n, m;
int fa[maxn];
int vis[maxn];
void init() {
    for (int i = 0; i < maxn; i++)
        fa[i] = i, vis[i] = 0;
}
inline int findFa(int x) {
    if (x == fa[x])
        return x;
    else
        return fa[x] = findFa(fa[x]);
}
inline void Union(int x, int y) {
    int fax = findFa(x);
    int fay = findFa(y);
    if (fax == fay)
        return;
    else {
        fa[fax] = fay;
    }
}
int main() {
    cin >> m >> n;
    init();
    for (int i = 1; i <= m; i++) {
        int x = read;
        for (int j = 1; j <= x; j++) {
            int t = read;
            if (vis[t])
                Union(vis[t], i);
            else
                vis[t] = i;
        }
    }
    int ans = 0;
    for (int i = 1; i <= m; i++) {
        if (i == fa[i])
            ans++;
    }
    cout << m - ans << endl;
    return 0;
}
posted @ 2021-05-08 10:56  PushyTao  阅读(37)  评论(0编辑  收藏  举报