ACM ArabellaCPC 2015F题 并查集

来源:互联网 发布:高性能php架构 编辑:程序博客网 时间:2024/06/07 05:52

传送门: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\n", ans);        }    }    return 0;}


0 0
原创粉丝点击