分类目录归档:并查集

洛谷 P1197 [JSOI2008]星球大战

总算是没看题解自己A了一道题,呜呜呜。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#include<iostream>
#include<vector>
#include<cstring>
#include<stack>
#include<queue>
using namespace std;
int father[400005];
int _find(int node){
    if(father[node]==-1)return node;
    return father[node]=_find(father[node]);
}
bool _union(int x,int y){
    if(_find(x)==_find(y))return false;
    father[_find(x)]=_find(y);
    return true;
}
int n,m,k;
bool alive[400005];
vector<int> edges[400005];
stack<int> ans;
stack<int> q;
int cnt,cntn;
int main(){
    ios::sync_with_stdio(false);
    memset(father,-1,sizeof(father));
    memset(alive,true,sizeof(alive));
    cin>>n>>m;
    cnt=0;cntn=n;
    for(int i=1;i<=m;i++){
        int x,y;
        cin>>x>>y;
        edges[x].push_back(y);
        edges[y].push_back(x);
    }
    cin>>k;
    for(int i=1;i<=k;i++){
        int v;
        cin>>v;
        alive[v]=false;
        q.push(v);
        cntn--;
    }
    for(int i=0;i<n;i++){
        if(!alive[i])continue;
        for(int j=0;j<edges[i].size();j++){
            if(!alive[edges[i][j]])continue;
            if(_union(i,edges[i][j]))cnt++;
        }
    }
    ans.push(cntn-cnt);
    while(!q.empty()){
        int cur=q.top();q.pop();
        cntn++;
        alive[cur]=true;
        for(int i=0;i<edges[cur].size();i++){
            if(!alive[edges[cur][i]])continue;
            if(_union(cur,edges[cur][i]))cnt++;
        }
        ans.push(cntn-cnt);
    }
    while(!ans.empty()){
        cout<<ans.top()<<endl;
        ans.pop();
    }
}

洛谷 P3367 【模板】并查集

明明记得之前应该有并查集的板子在博客里?怎么找不到了??

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include<iostream>
#include<string>
#include<cstring>
#include<algorithm>
using namespace std;
int father[10005];
int _find(int num) {
    if (father[num] == -1)return num;
    else return father[num] = _find(father[num]);
}
void _union(int v1, int v2) {
    if (_find(v1) == _find(v2))return;
    father[_find(v2)] = v1;
}
int n, m;
int main(){
    memset(father, -1, sizeof(father));
    cin >> n >> m;
    while (m--) {
        int z, x, y;
        cin >> z >> x >> y;
        if (z == 1)_union(x, y);
        else cout << (_find(x) == _find(y) ? 'Y' : 'N') << endl;
    }
}

洛谷 银河英雄传说

题号:P1196
参见题解:https://www.luogu.org/wiki/show?name=%E9%A2%98%E8%A7%A3+P1196
结合源代码阅读才好……
推荐题解作者:作者: 超神火星人 更新时间: 2017-04-29 09:14

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include<iostream>
#include<algorithm>
#include<string>
#include<cstdlib>
#include<cstring>
#include<utility>
int father[30005],size[30005],front[30005];
using namespace std;
int sfind(int node){
    if (father[node] == -1)return node;
    int fn = sfind(father[node]);
    front[node] += front[father[node]];
    return father[node]=fn;
}
int main(){
    for (int i = 1; i <= 30000; i++){
        father[i] = -1;
        size[i] = 1;
        front[i] = 0;
    }
    ios::sync_with_stdio(false);
    int n;
    cin >> n;
    while (n--){
        char c;
        int rf1, rf2;
        cin >> c >> rf1 >> rf2;
        int fa1 = sfind(rf1);
        int fa2 = sfind(rf2);
        switch (c){
        case 'M':
            front[fa1] += size[fa2];
            father[fa1] = fa2;
            size[fa2] += size[fa1];
            size[fa1] = 0;
            break;
        case 'C':
            if (fa1 != fa2)cout << "-1" << endl;
            else cout << abs(front[rf1] - front[rf2])-1 << endl;
            break;
        }
    }
}

20180815更新:
重做了这道题,还是看的这个人的题解。。。。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include<iostream>
using namespace std;
int t;
int father[30005],front[30005],num[30005];
int _find(int node){
    if(father[node]==0)return node;
    int fn=_find(father[node]);
    front[node]+=front[father[node]];
    return father[node]=fn;
}
int main(){
    ios::sync_with_stdio(false);
    for(int i=1;i<=30000;i++)num[i]=1;
    cin>>t;
    while(t--){
        char op;
        int x,y;
        cin>>op>>x>>y;
        int fx=_find(x),fy=_find(y);
        if(op=='M'){
            front[fx]+=num[fy];
            father[fx]=fy;
            num[fy]+=num[fx];
            num[fx]=0;
        }else{
            if(fx!=fy)cout<<-1<<endl;
            else cout<<abs(front[x]-front[y])-1<<endl;
        }
    }  
}

发现越到后面就越感觉是在抄题解怎么办,想也想不出来。

洛谷 关押罪犯

题号:1525
参见题解:作者: 超级范范 更新时间: 2017-07-23 17:05
https://www.luogu.org/wiki/show?name=%E9%A2%98%E8%A7%A3+P1525

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int father[40005];
struct s{
    int u, v, w;
    bool operator < (s & s1){
        return w>s1.w;
    }
}arr[100005];
int _find(int node){
    if (father[node] == -1)return node;
    return father[node] = _find(father[node]);
}
void merge(int x, int y){
    x = _find(x);
    y = _find(y);
    if (x != y)father[x] = y;
}
bool sameset(int x, int y){
    return _find(x) == _find(y);
}
int main(){
    memset(father, -1, sizeof(father));
    ios::sync_with_stdio(false);
    int n, m;
    cin >> n >> m;
    for (int i = 1; i <= m; i++){
        cin >> arr[i].u >> arr[i].v >> arr[i].w;
    }
    sort(arr + 1, arr + m + 1);
    int maxw = 0;
    for (int i = 1; i <= m; i++){
        if (sameset(arr[i].u, arr[i].v)){
            if (arr[i].w > maxw){
                cout << arr[i].w;
                return 0;
            }
        }
        else{
            merge(arr[i].u, arr[i].v + n);
            merge(arr[i].v, arr[i].u + n);
        }
    }
    cout << 0;
}

20180814更新:除了并查集做法还有二分图做法,应该也很好做,不写了。
题解:https://www.luogu.org/blog/Kesdiael3/solution-p1525

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include<iostream>
#include<algorithm>
using namespace std;
int n,m;
struct p{
    int a,b,c;
    bool operator < (const p& p2) const{
        return c>p2.c;
    }
}ps[100005];
int father[40005];
int _find(int x){
    if(father[x]==0)return x;
    return father[x]=_find(father[x]);
}
bool _union(int x,int y){
    if(_find(x)==_find(y))return false;
    father[_find(x)]=_find(y);
    return true;
}
int main(){
    ios::sync_with_stdio(false);
    cin>>n>>m;
    for(int i=1;i<=m;i++)cin>>ps[i].a>>ps[i].b>>ps[i].c;
    sort(ps+1,ps+m+1);
    for(int i=1;i<=m;i++){
        if(_find(ps[i].a)==_find(ps[i].b)){
            cout<<ps[i].c;
            return 0;
        }else{
            _union(ps[i].a,ps[i].b+n);
            _union(ps[i].b,ps[i].a+n);
        }
    }
    cout<<0;
}