• ACM ArabellaCPC 2015F题 并查集


    传送门:https://odzkskevi.qnssl.com/1110bec98ca57b5ce6aec79b210d2849?v=1492616502 

    题意:先给一个样例数,每个样例n,m分别表示字符串的长度和要给出的关系数

    给出的关系,两个位置上的字符(从1开始的下标)必须相等。最后满足这个字符串还是一个回文串 。

    字符串的长度达到了50000,关系数上限有10000.这里肯定要有一种数据结构来压缩时间。。。


    思路:用并查集来维护要处理的关系,注意这里的并查集是维护关系不是集合。回文串和给出的关系都是要促成相等关系,所以将对称和给出关系的字符用并查集来维护即可。

    总体思路就是找出独立的?也就是不受关系约束和回文串约束的?,这里每次找父节点时,优先将字符当做爸爸,然后在下面遍历中将?覆盖。双??下的情况,将其中一个作为爸爸,遍历不能覆盖,但是num++的时候判断下爸爸就行了,没被覆盖仍未初始化-1的才能num+1.

    最后注意取模和long long。。。。


    #include <bits/stdc++.h>
    
    using namespace std;
    typedef long long ll;
    const int mod = 1e9+7;
    const int maxn = 50000+10;
    int f[maxn];
    string str;
    int flag;
    
    
    int getf(int u)
    {
        if(f[u]==-1)
            return u;//返回他本身下标
        else
            f[u] = getf(f[u]);
        return f[u];
    }
    
    void Merge(int tt1,int tt2)//找爸爸
    {
        tt1 = getf(tt1);
        tt2 = getf(tt2);
        if(tt1!=tt2)
        {
            if(str[tt1]=='?')
                f[tt1] = tt2;//优先将字符做爸爸
            else
                f[tt2] = tt1;
        }
    }
    int main()
    {
    //    freopen("in.txt","r",stdin);
        int T;
        cin>>T;
        while(T--) {
        int n,m;
        int num = 0;
        int flag = 0;
        ll ans = 1;
        memset(f,-1,sizeof(f));
        cin>>n>>m;
        cin>>str;
        for(int i=0; i<n; i++)
            Merge(i, n-1-i);
        while(m--)
        {
            int t1,t2;
            cin>>t1>>t2;
            t1--;
            t2--;
            Merge(t1,t2);
        }
        for(int i = 0; i < n; i++)
        {
            int pos = getf(i);
            if(str[i]=='?'&& str[pos] != '?')//覆盖
                str[i] = str[pos];
            if(str[i]!='?'&& str[pos] !='?' && str[i]!=str[pos])
            {
                puts("0");
                flag = 1;
                break;
            }
    
        }
        if(!flag) {
            for(int i=0; i<n; i++) {
                if(str[i]=='?' && f[i] == -1) { //防止对称的两个?,这里只取一个
                    num++;
                    }
                }
                for(int i =0 ; i<num; i++)
                    ans = (ans*26 )%mod;
                printf("%lld
    ", ans);
            }
        }
        return 0;
    }
    


  • 相关阅读:
    P3386 【模板】二分图最大匹配 题解(匈牙利算法)
    B. Repetitions Decoding 题解(思维+构造)
    D. Big Brush 题解(构造+bfs)
    软件使用 蓝湖的基础使用
    破解版navicate数据库 15版本
    大腕web2.0版
    JPA(JPQL)批量操作的示例及真实执行逻辑
    Java线程池的使用示例及注意事项
    解决docker开启端口映射后,会直接穿透本机防火墙的问题
    PostgreSQL用户访问多个schema及其他常用命令
  • 原文地址:https://www.cnblogs.com/zhangmingzhao/p/7256625.html
Copyright © 2020-2023  润新知