带权并查集

学习链接:https://blog.csdn.net/chenguolinblog/article/details/7985370?spm=a2c4e.10696291.0.0.2ce319a4sYGZPg

习题链接:https://yq.aliyun.com/articles/252458?spm=a2c4e.11153940.0.0.42a1757bQt463q

How many answers are wrong

HDU 3038

题解&代码:https://www.cnblogs.com/liyinggang/p/5327055.html

#include <stdio.h>
#include <algorithm>
#include <string.h>
using namespace std;
const int N =200010;
int father[N];
int sum[N];  ///记录当前结点到根结点的距离

int _find(int x){
    if(x!=father[x]){
        int t = father[x];
        father[x] = _find(father[x]);
        sum[x]+=sum[t];
    }
    return father[x];
}
int main()
{
    int n,m;
    while(scanf("%d%d",&n,&m)!=EOF){
        for(int i=0;i<=n;i++){
            father[i] = i;
            sum[i] = 0;
        }
        int ans = 0;
        while(m--){
            int a,b,v;
            scanf("%d%d%d",&a,&b,&v);
            a--;
            int roota = _find(a);
            int rootb = _find(b);
            if(roota==rootb){
                if(sum[a]-sum[b]!=v) ans++;  ///精华部分1
            }
            else{
                father[roota] = rootb;
                sum[roota] = -sum[a]+sum[b]+v; ///精华部分2
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}

食物链

POJ 1182
代码&题解:https://blog.csdn.net/chenguolinblog/article/details/8019237?spm=a2c4e.10696291.0.0.79a919a4kzULr0

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
 
const int MAXN = 50010;
 
int n , m , ans;
int father[MAXN];
int rank[MAXN];
 
void init(){
    ans = 0;
    memset(rank , 0 , sizeof(rank));
    for(int i = 1 ; i <= n ; i++)
        father[i] = i;
}
 
int find(int x){
    if(x != father[x]){
        int fa = father[x];    
        father[x] = find(father[x]);
        rank[x] += rank[fa];
        rank[x] %= 3;
    }
    return father[x];
}
 
void solve(int mark , int x , int y){
    if(x > n || y > n){
        ans++;
        return;
    }
    int fx = find(x);
    int fy = find(y);
    int v = mark == 1 ? 0 : 1;
    if(fx != fy){
       father[fx] = fy;
       rank[fx] = (rank[y]+v-rank[x]+3)%3;
    }
    else{
       if(rank[x] != (rank[y]+v)%3)
         ans++;
    }
}
 
int main(){
    int mark , x , y;
    scanf("%d%d" , &n , &m);
    init();
    ans = 0;
    for(int i = 0 ; i < m ; i++){
        scanf("%d%d%d" , &mark , &x , &y);         
        solve(mark , x , y);
    }
    printf("%d\n" , ans);
    return 0;
}
 

Find them, Catch them

POJ 1703
题解&代码:https://blog.csdn.net/chenguolinblog/article/details/8016538?spm=a2c4e.10696291.0.0.55e419a43rIuk6

 
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
 
const int MAXN = 1e5+10;
 
int father[MAXN];
int rank[MAXN];
 
void init(int n){
    memset(rank , 0 , sizeof(rank));
    for(int i = 1 ; i <= n ; i++)
        father[i] = i;
}
 
int find(int x){
    if(x != father[x]){
        int fa = father[x]; 
        father[x] = find(fa); 
        rank[x] += rank[fa];
        rank[x] %= 2;
    }
    return father[x];
}
 
void output(int x , int y , int fx , int fy){
    if(fx != fy)
        puts("Not sure yet.");
    else{
        if(rank[x] == rank[y])  
            puts("In the same gang.");
        else
            puts("In different gangs.");
    }
}
 
int main(){
    char ch;
    int x , y;
    int cas , n , m;
    scanf("%d" , &cas);
    while(cas--){
        scanf("%d%d%*c" , &n , &m);
        init(n); 
        while(m--){
            scanf("%c %d %d%*c" , &ch , &x , &y); 
            int fx = find(x);    
            int fy = find(y);    
            if(ch == 'A'){
                output(x , y , fx , fy);
            }
            else{
                if(fx != fy){
                    father[fx] = fy;
                    rank[fx] = (rank[y]+1-rank[x]+2)%2;
                }   
            }
        }
    }
    return 0;
}
 

Cube Stacking

POJ 1988
题解&代码:https://blog.csdn.net/chenguolinblog/article/details/8026631?spm=a2c4e.10696291.0.0.255519a4pSwi51

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
 
const int MAXN = 300010;
 
int father[MAXN];
int rank[MAXN]; 
int max_rank[MAXN];
 
void init(int n){
    memset(rank , 0 , sizeof(rank));    
    memset(max_rank , 0 , sizeof(max_rank));    
    for(int i = 1 ; i <= n ; i++)
        father[i] = i;
}
 
int find(int x){
    if(father[x] != x){
       int fa = father[x];
       father[x] = find(fa);
       rank[x] += rank[fa];
    }
    return father[x];
}
 
void move(int x , int y){
    int fx = find(x);
    int fy = find(y);
    if(fx != fy){
        father[fx] = fy;
        rank[fx] = max_rank[fy]+1;
        max_rank[fy] += max_rank[fx]+1;
    }
}
 
int main(){
    char ch;
    int n , x , y;
    while(scanf("%d%*c" , &n) != EOF){
         init(n);
         for(int i = 0 ; i < n ; i++){
            scanf("%c" , &ch); 
            if(ch == 'M'){
               scanf("%d%d%*c" , &x , &y); 
               move(x , y);
            }
            else{
               scanf("%d%*c" , &x);          
               int fx = find(x);// 注意先压缩
               printf("%d\n" , rank[x]);
            }
         } 
    }
    return 0;
}
 

Supermarket

POJ 1456
贪心+并查集
题解&代码:https://blog.csdn.net/chenguolinblog/article/details/9785381?spm=a2c4e.10696291.0.0.113c19a4siAHbL

 
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
 
const int MAXN = 10010;
 
struct Node{
    int val;
    int day; 
    bool operator<(const Node &s)const{
        return val > s.val;
    }
};
Node node[MAXN];
int father[MAXN];
 
int find(int x){
    if(father[x] != x)
        father[x] = find(father[x]);
    return father[x];
}
 
int solve(int n){
    int ans = 0;
    for(int i = 1 ; i <= n ; i++){
        int fa = find(node[i].day);
        if(fa > 0){
            father[fa] = fa-1; 
            ans += node[i].val;
        }
    }
    return ans;    
}
 
int main(){
    int n;  
    while(scanf("%d" , &n) != EOF){
         for(int i = 1 ; i < MAXN ; i++)
             father[i] = i;
         for(int i = 1 ; i <= n ; i++)
             scanf("%d%d" , &node[i].val , &node[i].day);
         sort(node+1 , node+n+1);
         printf("%d\n" , solve(n));
    }
    return 0;
}
 

Parity game

POJ 1733
代码&题解:https://blog.csdn.net/chenguolinblog/article/details/9811385?spm=a2c4e.10696291.0.0.6c8d19a4rOQoAN

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
 
const int MAXN = 50010;
 
struct Node{
    int x;
    int y;
    int mark; 
};
Node node[MAXN];
int arr[MAXN] , pos;
int father[MAXN] , Rank[MAXN] , num;
 
void init(){
    sort(arr , arr+pos);
    num = unique(arr , arr+pos)-arr;
    memset(Rank , 0 , sizeof(Rank));
    for(int i = 0 ; i <= num ; i++)
        father[i] = i;
}
 
int find(int x){
    if(father[x] != x){
        int fa = father[x];
        father[x] = find(father[x]);
        Rank[x] = (Rank[x]+Rank[fa])%2;
    }
    return father[x];
}
 
int search(int x){
    int left = 0;
    int right = num-1;
    while(left <= right){
        int mid = (left+right)>>1;
        if(arr[mid] == x)
            return mid; 
        else if(arr[mid] < x)
            left = mid+1;
        else 
            right = mid-1;
    }
}
 
int solve(int n){
    for(int i = 0 ; i < n ; i++){
        int x = search(node[i].x)+1;    
        int y = search(node[i].y)+1;    
        int fx = find(x); 
        int fy = find(y);
        int val = node[i].mark;
        if(fx == fy){
            if((Rank[x]-Rank[y]+2)%2 != val) 
                return i;
        }
        else{
            father[fx] = fy;
            Rank[fx] = (val+Rank[y]-Rank[x]+2)%2;
        }
    }
    return n;
}
 
int main(){
    int len , n;
    char str[10];
    while(scanf("%d%d" , &len , &n) != EOF){
        pos = 0;
        for(int i = 0 ; i < n ; i++){ 
            scanf("%d %d %s" , &node[i].x , &node[i].y , str);
            node[i].x--;
            arr[pos++] = node[i].x;
            arr[pos++] = node[i].y;
            if(str[0] == 'e')
                node[i].mark = 0;
            else
                node[i].mark = 1;
        }
        init();
        printf("%d\n" , solve(n));
    }
    return 0;
}
/*
10
5
1 2 even
3 4 odd
5 6 even
1 6 even
7 10 odd

*/
 

Rochambeau

POJ 2912
代码&题解:https://blog.csdn.net/chenguolinblog/article/details/9842135?spm=a2c4e.10696291.0.0.7a6519a44ICDgT

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值