2600 城镇规划 (并查集 set)

本文介绍了一种基于并查集和set数据结构的算法,用于解决《都市:天际线》游戏中贸易路径的可行性问题。通过维护道路颜色和可达点集,实时判断贸易路径的有效性,适用于城市规划与贸易模拟。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

2600 城镇规划 (并查集 set)

小A最近在玩《都市:天际线》这款游戏,他在不断地建设着自己的城市(比如说修路盖房这种)。 

但是一个没有贸易的城市是没有灵魂的,所以小A的城市中有许许多多的贸易来往,给这个城市带来源源不断的资金。 

然而小A为了展现自己高超的游戏技巧,给自己打了一个增加游戏难度的mod,使得贸易的难度陡然上升。 

在这个mod中,城市中的每一条路都有一个颜色C,假设贸易经过的路径序列为Ci(i=1,2,…,n),那么需要满足C_(2*k-1)=C_(2*k) (2*k<=n)的路径才能够成功完成这个贸易,否则就会出现诸如强盗打劫货物,货车翻车等事件导致贸易失败。 

但是小A其实并没有100%计算正确的信心,所以他希望你能一直帮忙告诉他,他下一次准备进行的从A点到B点的贸易是否能够成功,由于小A的城市在不断施工,所以随时可能有一条路被建成。

 

 

#include<bits/stdc++.h>
using namespace std;
const int M=100005;
int n,m,Q,tot,fa[M],head[M],Next[M*4],vet[M*4],w[M*4];
set<int> s[M]; //s[i]表示i走一步可到达的点集
set<int>::iterator it;
int find(int x){
    if(fa[x]!=x) fa[x]=find(fa[x]);
    return fa[x];
}
void hb(int x,int y){ //合并x和y所在集合,包括set的合并
    int p=find(x), q=find(y);
    if(p==q) return;
    if(s[p].size()<s[q].size()) swap(p,q);
    fa[q]=p; //让小集合q合并到大集合p中
    for(it=s[q].begin(); it!=s[q].end(); it++) s[p].insert(*it);
    s[q].clear();
}
void unionset(int x,int y,int z){
    //x和y的边表中颜色也为z的点合并
    for(int i=head[y]; i; i=Next[i]){
        if(w[i]==z) hb(x,vet[i]);
    }
}
void add(int x,int y,int z){
    Next[++tot]=head[x], vet[tot]=y, w[tot]=z;
    head[x]=tot;
}
void work(int x,int y,int z){
    int p=find(x), q=find(y);
    s[p].insert(y), s[q].insert(x); //走一步可达
    unionset(x,y,z); unionset(y,x,z);
    add(x,y,z); add(y,x,z);
}
int main(){
    scanf("%d%d%d",&n,&m,&Q);
    for(int i=1; i<=n; i++) fa[i]=i;
    for(int i=1; i<=m; i++){
        int x,y,z; scanf("%d%d%d",&x,&y,&z);
        work(x,y,z);
    }
    for(int i=1; i<=Q; i++){
        char op[3]; scanf("%s",op);
        int x,y,z;
        if(op[0]=='?'){
            scanf("%d%d",&x,&y);
            int p=find(x), q=find(y);
            //printf("x=%d y=%d p=%d q=%d\n",x,y,p,q);
            if(p==q || s[p].find(y)!=s[p].end()) printf("Yes\n");
            else printf("No\n");
        }else{
            scanf("%d%d%d",&x,&y,&z);
            work(x,y,z);
        }
    }return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值