码迷,mamicode.com
首页 > 其他好文 > 详细

HDU3461(并查集)

时间:2015-03-17 15:56:11      阅读:156      评论:0      收藏:0      [点我收藏+]

标签:并查集

题目链接:点击打开链接


解题思路:

一道看不出来是并查集的并查集题,做来做去还是觉得九野的题集不错。题目大意就是有一个n位的密码串,每位可能是a到z间的任意一个字母。m行输入区间[ l , r],代表这个区间可以同时做+1操作,如果一组密码通过有限次增加变成另一组密码,那么我们认为这两组密码是相同的。求在m个区间下有多少种不同的密码。

暴力来看是求26^n,当有cnt个不同区间加进来后,答案为26^(n - cnt)。我们另 f 数组全部初始化为-1,然后对于区间[ l , r ],我们用f[ l ] = r + 1来表示。每次操作,如果不存在区间[ l , r ],那么cnt ++。

最后计算下26^(n - cnt)即可。


完整代码:

#include <algorithm>
#include <iostream>
#include <cstring>
#include <climits>
#include <cstdio>
#include <string>
#include <cmath>
#include <map>
#include <queue>
using namespace std;
typedef long long LL;
const int MOD = int(1e9)+7;
const int INF = 0x3f3f3f3f;
const double EPS = 1e-9;
const double PI = acos(-1.0); //M_PI;
int n , m;
const int maxn = 10000001;
int f[maxn];

int find(int x)
{
    return f[x] == -1 ? x : find(f[x]);
}

bool unin(int a , int b)
{
    int x = find(a);
    int y = find(b);
    if(x == y)  return false;
    f[x] = y;
    return true;

}

LL pow(int x)
{
    LL res = 1;
    for(int i = 0 ; i < x ; i ++)
    {
        res *= 26;
        res %= MOD;
    }
    return res;
}

int main()
{
    #ifdef DoubleQ
    freopen("in.txt","r",stdin);
    #endif
    while(cin >> n >> m)
    {
        memset(f , -1 , sizeof(f));
        int cnt = 0;
        int l , r;
        for(int i = 0 ; i < m ; i ++)
        {
            cin >> l >> r;
            if(unin(l , r + 1))
                cnt ++;
        }
        cout << pow(n - cnt) << endl;
    }
}


更多精彩:点击打开链接

HDU3461(并查集)

标签:并查集

原文地址:http://blog.csdn.net/u013447865/article/details/44341685

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!