Kruskal重构树-进阶

例题一:区间最小生成树

Kruskal重构树-进阶
#include<bits/stdc++.h>
using namespace std;
#define re register int
#define LL long long

static char buf[1<<20], *p1=buf, *p2=buf;
#define getchar() p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<20, stdin), p1==p2)?EOF:*p1++
inline int read()
{
    int x=0;char c=getchar();
    while(c<0||c>9)c=getchar();
    while(0<=c&&c<=9)x=x*10+c-48,c=getchar();
    return x;
}
const int N=30005;

int n, m, q;

int fa[N];int getf(int x){return x==fa[x]?x:fa[x]=getf(fa[x]);}

struct node{int x, y, z;}rdin[N];
vector<node> G[N<<3];

vector<node> update(vector<node>A, vector<node>B)
{
    vector<node>ret;
    ret.clear();
    int i=0, j=0, cnt=0;
    int p=A.size(), q=B.size();
    for(re o=1;o<=n;++o)fa[o]=o;
    while(i<p&&j<q&&cnt<n-1)
    {
        if(A[i].z<=B[j].z)
        {
            int f1=getf(A[i].x), f2=getf(A[i].y);
            if(f1!=f2)
            {
                cnt++;
                fa[f1]=f2;
                ret.push_back(A[i]);
            }
            i++;
        }
        else
        {
            int f1=getf(B[j].x), f2=getf(B[j].y);
            if(f1!=f2)
            {
                cnt++;
                fa[f1]=f2;
                ret.push_back(B[j]);
            }
            j++;
        }
    }
    while(i<p&&cnt<n-1)
    {
        int f1=getf(A[i].x), f2=getf(A[i].y);
        if(f1!=f2)
        {
            cnt++;
            fa[f1]=f2;
            ret.push_back(A[i]);
        }
        i++;
    }
    while(j<q&&cnt<n-1)
    {
        int f1=getf(B[j].x), f2=getf(B[j].y);
        if(f1!=f2)
        {
            cnt++;
            fa[f1]=f2;
            ret.push_back(B[j]);
        }
        j++;
    }
    return ret;
}
void modi(int p, int l, int r, int id, node w)
{
    if(l == id && id == r)
    {
        G[p].clear();
        G[p].push_back(w);
        return;
    }
    int mid=(l+r)>>1, ls=(p<<1), rs=(p<<1|1);
    if(id <= mid) modi(ls, l, mid, id, w);
    else modi(rs, mid+1, r, id, w);
    
    G[p] = update(G[ls], G[rs]);
}
void build(int p, int l, int r)
{
    if(l == r)
    {
        G[p].push_back(rdin[l]);
        return;
    }
    int mid=(l+r)>>1, ls=(p<<1), rs=(p<<1|1);
    build(ls, l, mid);
    build(rs, mid+1, r);
    G[p]=update(G[ls], G[rs]);
}
vector<node> query(int p, int l, int r, int x, int y)
{
    if(x <= l && r <= y) return G[p];
    int mid=(l+r)>>1, ls=(p<<1), rs=(p<<1|1);
    if(x<=mid && y<=mid)return query(ls, l, mid, x, y);
    if(x>mid && y>mid)return query(rs, mid+1, r, x, y);
    vector<node>A, B;
    A=query(ls, l, mid, x, y);
    B=query(rs, mid+1, r, x, y);
    return update(A, B);
}

int work(vector<node>A)
{
    for(re i=1;i<=n;++i)fa[i]=i;
    int k=0, sz = A.size(), ret=0, cnt=0;
    while(k<sz && cnt<n-1)
    {
        int f1=getf(A[k].x), f2=getf(A[k].y), v=A[k].z;
        if(f1!=f2)
        {
            fa[f1]=f2;
            ret+=v;
            cnt++;
        }
        k++;
    }
    return cnt==n-1?ret:-1;
}
int main()
{
    n=read();m=read();q=read();
    for(re i=1;i<=m;++i)
    {
        int x=read(), y=read(), z=read();
        rdin[i]=(node){x, y, z};
    }
    build(1, 1, m);
    while(q--)
    {
        int t, k, x, y, z;
        t=read();
        if(t==1)
        {
            k=read();x=read();y=read();z=read();
            modi(1, 1, m, k, (node){x, y, z});
        }
        else
        {
            x=read();y=read();
            int Ans = work(query(1, 1, m, x, y));
            if(Ans == -1) puts("Impossible");
            else printf("%d\n", Ans);
        }
    }
    return 0;
}
View Code

例题二:城市建设

Kruskal重构树-进阶
#include<bits/stdc++.h>
using namespace std;
#define re register int
#define LL long long
#define py pair<int,int>
#define fi first
#define se second

static char buf[1<<20], *p1=buf, *p2=buf;
#define getchar() p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<20, stdin), p1==p2)?EOF:*p1++
inline int read()
{
    int x=0;
    char c=getchar();
    while(c<0||c>9)c=getchar();
    while(0<=c&&c<=9)x=(x<<3)+(x<<1)+c-48,c=getchar();
    return x;
}

const int N=5e4+5, INF=1e9;


struct node{
    int x, y, v, id;
    bool operator<(const node&p)const{
        return v < p.v;
    }
};
node E[30][N], t[N], nw[N];
int rak[N], A[N];
LL Ans[N];
py ask[N];

int fa[N];int getf(int x){return x==fa[x]?x:fa[x]=getf(fa[x]);}
LL suodian(int &tot)
{// 合并一定需要的边 
    for(re i=1;i<=tot;++i) fa[t[i].x]=t[i].x, fa[t[i].y]=t[i].y;
    int cnt=0; LL val=0;
    sort(t+1, t+1+tot); 
    for(re i=1;i<=tot;++i)
    {
        int x=t[i].x, y=t[i].y;
        if(getf(x)!=getf(y))
        {
            fa[getf(x)]=getf(y);
            nw[++cnt]=t[i];
        }
    }
    for(re i=1;i<=cnt;++i) fa[nw[i].x]=nw[i].x, fa[nw[i].y]=nw[i].y;
    for(re i=1;i<=cnt;++i)
    {
        int x=nw[i].x, y=nw[i].y, v=nw[i].v;
        if(v!=-INF)
        {
            fa[getf(x)]=getf(y);
            val += v;
        }
    }
    cnt=0;
    for(re i=1;i<=tot;++i)
    {
        int x=t[i].x, y=t[i].y;
        if(getf(x)!=getf(y))
        {
            nw[++cnt]=t[i];
            nw[cnt].x=getf(x);
            nw[cnt].y=getf(y);
            rak[t[i].id]=cnt;
        }
    }
    tot=cnt;
    for(re i=1;i<=tot;++i)t[i]=nw[i];
    return val;
}
void qubian(int &tot)
{ // 去除一定不需要的边 
    for(re i=1;i<=tot;++i) fa[t[i].x]=t[i].x, fa[t[i].y]=t[i].y;
    int cnt=0;
    sort(t+1, t+1+tot);
    for(re i=1;i<=tot;++i)
    {
        int x=t[i].x, y=t[i].y, v=t[i].v;
        if(getf(x)==getf(y))
        {
            if(v==INF)
                nw[++cnt]=t[i];
        }
        else
        {
            fa[getf(x)]=getf(y);
            nw[++cnt]=t[i];
        }
    }
    tot=cnt;
    for(re i=1;i<=tot;++i)t[i]=nw[i];
}
void CDQ(int l, int r, int d, int tot, LL val)
{// 左,右,深度,边的总数,合并成点的贡献 
    if(l == r) A[ask[l].fi] = ask[l].se; // 更新边权 
    for(re i=1;i<=tot;++i)
    {
        t[i] = E[d][i]; // 继承 
        t[i].v = A[t[i].id]; // 边权更新 
        rak[t[i].id] = i; // 原边在新数组中的编号 
    }
    if(l == r)
    {
        for(re i=1;i<=tot;++i) fa[t[i].x] = t[i].x, fa[t[i].y] = t[i].y;
        sort(t+1, t+1+tot);//kruskal
        Ans[l] = val;
        for(re i=1;i<=tot;++i)
        {
            int x=t[i].x, y=t[i].y, v=t[i].v;
            if(getf(x) != getf(y))
            {
                fa[getf(x)] = getf(y);
                Ans[l] += v;
            }
        }
        return;
    }
    for(re i=l;i<=r;++i) t[rak[ask[i].fi]].v = -INF;
    val += suodian(tot);
    for(re i=l;i<=r;++i) t[rak[ask[i].fi]].v = INF;
    qubian(tot);
    
    for(re i=1;i<=tot;++i) E[d+1][i] = t[i];
    int mid = (l+r)>>1;
    CDQ(l, mid, d+1, tot, val);
    CDQ(mid+1, r, d+1, tot, val);
}

int main()
{
    int n=read(), m=read(), q=read();
    for(re i=1;i<=n;++i)fa[i]=i;
    for(re i=1;i<=m;++i)
    {
        int x=read(), y=read(), z=read();
        A[i]=z; // 原边权记录一下 
        E[0][i]=(node){x, y, z, i}; // 左右端点,边权,在原数组的编号 
    }
    for(re i=1;i<=q;++i)
    {
        int x=read(), y=read();
        ask[i]=py(x, y);
    }
    CDQ(1, q, 0, m, 0); // 分治 
    for(re i=1;i<=q;++i)printf("%lld\n", Ans[i]);
    return 0;
}
View Code

 

Kruskal重构树-进阶

上一篇:DNS域传送漏洞——由于DNS服务器配置不当,可能导致攻击者获取某个域(域名)的所有(子域名)记录


下一篇:oracle:ora-12560 tns 协议适配器错误