• Codeforces 1166 F. Vicky's Delivery Service 并查集+set


    题意:有n个点,m条边,边有c种颜色,q次操作。

    每个边都有一种颜色。

    然后操作有两种,一种是再加一条边,另一种是查询能否从x达到y。

    移动的限制是,连着走两步必须是同一种颜色,如果走奇数步,最后一步可以是任意颜色。

    例子:1-2-3-4-5-6。

    这个题颜色种类很多,我是用map<int,vector<int>>来存边。

    我们首先可以想到 对于点x同种颜色连着的点都是可以相互移动的,所以我们可以用这种方法将它们用并查集合并,我们也可以直接map<int,int>来存边,因为一个vector里的点是等价的。

    但是这样有一个问题,走偶数步可以走通的已经被我们合并可以直接查询了,那么最后一步能走到的怎么办呢?

    我们可以对每个联通集合存一个set,里面放集合中能一步走到的点。我们之后要合并集合,这个set自然也要合并,本来是想着用可并堆,但是其实用启发式合并也可以了。

    以下为代码:

    #include<bits/stdc++.h>
    using namespace std;
    int i,i0,n,m,c,q,pre[100005];
    map<int,vector<int>>mp[100005];
    set<int>dic[100005];
    int fin(int x){return (pre[x]==x)?x:pre[x]=fin(pre[x]);}
    void uni(int x,int y)
    {
        if(fin(x)!=fin(y))
        {
            if(dic[fin(x)].size()<dic[fin(y)].size())swap(x,y);
            for(auto i:dic[fin(y)])dic[fin(x)].insert(i),pre[fin(y)]=fin(x);
        }
    }
    void add()
    {
        int x,y,col;
        scanf("%d %d %d",&x,&y,&col);
        dic[fin(x)].insert(y),dic[fin(y)].insert(x);
        mp[x][col].push_back(y),uni(y,mp[x][col][0]);
        mp[y][col].push_back(x),uni(x,mp[y][col][0]);
    }
    int main()
    {
        scanf("%d %d %d %d",&n,&m,&c,&q);
        for(i=1;i<=n;i++)pre[i]=i;
        while(m--)add();
        while(q--)
        {
            char op;
            scanf(" %c",&op);
            if(op=='?')
            {
                int x,y;
                scanf("%d %d",&x,&y);
                printf("%s\n",(fin(x)==fin(y)||dic[fin(x)].count(y))?"Yes":"No");
            }
            else add();
        }
        return 0;
    }
    
  • 相关阅读:
    截取iOS系统返回事件
    iOS返回到指定界面
    swift 命名,字符串
    移动混合开发之文件管理Final之总结
    移动混合开发之android文件管理新建文件和删除文件
    移动混合开发之文件管理工具栏
    rem ,em ,px的区别
    移动混合开发之android文件管理-->flexbox,webFont。
    移动混合开发之android文件管理demo
    移动混合开发之页面布局
  • 原文地址:https://www.cnblogs.com/bitetheddddt/p/10896862.html
Copyright © 2020-2023  润新知