并查集优化连边

Posted uid001

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了并查集优化连边相关的知识,希望对你有一定的参考价值。

 

很多题目均可用并查集优化连边, 跳过一些已经访问过的点

比方说, 对[L,R]范围进行一定更新可以这样写

for (int i=Find(L); i<=R; i=Find(i)) {
    //do something
    fa[i] = i+1;
}

这样操作过后[L,R]的fa均指向R+1, 下一次会直接跳到R+1, 相当于每个点值只更新一次

 

例题

1, CF 827A

求构造一个最小字典序的字符串, 其中字符串某些位置的字符固定

 

技术分享图片
#include <iostream>
#define REP(i,a,n) for(int i=a;i<=n;++i)
using namespace std;
const int N = 2e6+10, INF = 0x3f3f3f3f;
int n, m;
int fa[N];
int Find(int x) {return fa[x]==x?x:fa[x]=Find(fa[x]);}
char s[N], t[N];

int main() {
    scanf("%d", &n);
    REP(i,1,N-1) fa[i]=i;
    int mx = 0;
    REP(i,1,n) {
        scanf("%s", t+1);
        m = strlen(t+1);
        int c, pos;
        scanf("%d", &c);
        while (c--) {
            scanf("%d", &pos);
            for (int j=Find(pos); j<=pos+m-1; j=Find(j)) {
                s[j] = t[j-pos+1];
                fa[j] = j+1;
            }
            mx = max(mx, pos+m-1);
        }
    }
    REP(i,1,mx) putchar(s[i]?s[i]:a);
}
View Code

 

 

2, hdu 5361 

直线上n个点, 点i能到达到i距离[li,ri]范围内的点, 花费ci, 求单源最短路

技术分享图片
#include <iostream>
#include <string.h>
#include <set>
#define REP(i,a,n) for(int i=a;i<=n;++i)
#define x first
#define y second
using namespace std;
typedef unsigned long long ll;
typedef pair<ll,int> pii;
const int N = 4e5+10;
const ll INF = 1LL<<60;
ll L[N], R[N], c[N], d[N];
int n, m, t, fa[N];
int Find(int x) {return fa[x]?fa[x]=Find(fa[x]):x;}

void dijkstra() {
    memset(d, 0x3f, sizeof d);
    memset(fa, 0, sizeof fa);
    set<pii> q;
    d[1] = 0;
    q.insert(make_pair(c[1],1));
    fa[1]=2;
    while (q.size()) {
        int u = q.begin()->y;q.erase(q.begin());
        for (int i:{-1,1}) {
            int l = u+i*L[u], r = u+i*R[u];
            if (l>r) swap(l,r);
            if (l>n||r<1) continue;
            l = max(1,l), r = min(n,r);
            for (int j=Find(l); j<=r; j=Find(j)) {
                if (j>r||j<l) break;
                if (d[j]>d[u]+c[u]) {
                    d[j]=d[u]+c[u];
                    q.insert({d[j]+c[j],j});
                }
                fa[j] = j+1;
            }
        }
    }
}


void work() {
    scanf("%d", &n);
    REP(i,1,n) scanf("%lld",L+i);
    REP(i,1,n) scanf("%lld",R+i);
    REP(i,1,n) scanf("%lld",c+i);
    dijkstra();
    REP(i,1,n) printf("%lld%c", d[i]>=d[0]?-1:d[i]," 
"[i==n]);
}

int main() {
    scanf("%d", &t);
    while (t--) work();
}
View Code

 

3, bzoj 2143

hdu的二维情况

技术分享图片
#include <iostream>
#include <queue>
#define REP(i,a,n) for(int i=a;i<=n;++i)
#define x first
#define y second
using namespace std;
typedef pair<int,int> pii;

const int N = 200;
int a[N][N], b[N][N], d[N][N], fa[N][N];
int n, m;
pii s[3];

struct _ {
    int x, y, w;
    bool operator < (const _ & rhs) const {
        return w>rhs.w;
    }
};

int Find(int fa[], int x) {return fa[x]==x?x:fa[x]=Find(fa,fa[x]);}

void dijkstra(pii s) {
    REP(i,1,n+20) REP(j,1,m+20) fa[i][j]=j;
    REP(i,1,n+20) REP(j,1,m+20) d[i][j]=0x3f3f3f3f;
    priority_queue<_> q;
    d[s.x][s.y]=0;
    q.push({s.x,s.y,a[s.x][s.y]});
    while (q.size()) {
        int x=q.top().x,y=q.top().y;q.pop();
        int l=max(1,x-b[x][y]),r=min(n,x+b[x][y]);
        REP(i,l,r) {
            int len = b[x][y]-abs(i-x);
            int u=max(1,y-len),D=min(m,y+len);
            for (int j=Find(fa[i],u); j<=D; j=Find(fa[i],j)) {
                if (d[i][j]>d[x][y]+a[x][y]) {
                    d[i][j]=d[x][y]+a[x][y];
                    q.push({i,j,d[i][j]+a[i][j]});
                }
                fa[i][j] = j+1;
            }
        }
    }
}

int dis[3];

int main() {
    scanf("%d%d", &n, &m);
    REP(i,1,n) REP(j,1,m) scanf("%d",&b[i][j]);
    REP(i,1,n) REP(j,1,m) scanf("%d",&a[i][j]);
    REP(i,0,2) scanf("%d%d",&s[i].x,&s[i].y);
    char ans = 0;
    int mi = 1e9;
    REP(i,0,2) { 
        dijkstra(s[i]);
        REP(j,0,2) dis[j] += d[s[j].x][s[j].y];
    }
    int p=min_element(dis,dis+3)-dis;
    if (dis[p]>1e8) return puts("NO"),0;
    printf("%c
%d
", p+X, dis[p]);
}
View Code

 

以上是关于并查集优化连边的主要内容,如果未能解决你的问题,请参考以下文章

CCA算法实现和优化

LsWn的数据结构并查集

树--12---并查集

力扣 每日一题 886. 可能的二分法难度:中等,rating: 1794(并查集 / 拆点优化的扩展域并查集)

关于并查集的一切全在这里了

BZOJ1202: [HNOI2005]狡猾的商人