ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

[洛谷P1525] 关押罪犯

2019-05-04 10:37:43  阅读:320  来源: 互联网

标签:P1525 cnt fx 关押 int fy get fa 洛谷


题目链接:

传送门

题目分析:

由最后划分的结果在两个集合,联想到二分图
又由于答案具有单调性,即如果当前答案可以则更大的答案也一定可以,想到二分答案
思路:
二分答案,每次对于答案进行检验,检验时将\(<=\)答案的边都忽略掉,只保留比答案大的边,然后进行染色判定二分图,如果能构成二分图,说明这些点可以被分在两个不同的集合,且由二分图的定义可以得到,集合内的点之间无连边,而两集合之间的连边在本题的背景下等于被断掉了,即可以保证有分配方案使得冲突值小于二分到的答案

代码:

#include<bits/stdc++.h>
#define N (100000+5)
#define mod (1000000000+7)
using namespace std;
inline int read() {
    int cnt = 0, f = 1; char c;
    c = getchar();
    while(!isdigit(c)) {
        if (c == '-') f = -1;
        c = getchar();
    }
    while(isdigit(c)) {
        cnt = cnt * 10 + c - '0';
        c = getchar();
    }
    return cnt * f;
}
int n, m, l1, l2, r1, r2, tot = 0;
int fa[N * 18], id[N][20], start[N * 18], base[20];
long long ans;
int get_father(int x) {
    if(fa[x] == x) return x;
    return fa[x] = get_father(fa[x]);
}

void merge(int x, int y) {
    int fx = get_father(x);
    int fy = get_father(y);
    if(fx > fy) swap(fx, fy);
    fa[fy] = fx;   //启发式合并 
}

int main() {
    base[0] = 1;
    for (register int i = 1; i <= 18; i++) base[i] = base[i-1] << 1;
    n = read(); m = read();
    if (n == 1) {
        printf("10\n");
        return 0;
    }
    for (register int i = 0; i <= 18; i++) 
        for (register int j = 1; j + base[i] - 1 <= n; j++) {
            id[j][i] = ++tot;
            fa[tot] = tot;
            start[tot] = j;
        }
        
/*-------------合并---------------*/
 
    for (register int i = 1; i <= m; i++) {
        l1 = read(); r1 = read(); l2 = read(); r2 = read();
        for (register int j = 18; j >= 0; --j) {
            if(l1 + base[j] - 1 <= r1) {
                merge(id[l1][j], id[l2][j]);
                l1 += base[j]; l2 += base[j];
            }
        }
    }

/*-------------下放-------------*/
 
    for (register int j = 18; j >= 1; --j) 
        for (register int i = 1; i + base[j] - 1 <= n; i++) {
            int f = get_father(id[i][j]); int s = start[f];
            merge(id[i][j - 1], id[s][j - 1]);
            merge(id[i + base[j - 1]][j - 1], id[s + base[j - 1]][j - 1]);
        }
        
    ans = 9;
    
    for (register int i = 2; i <= n; i++) {
        if(fa[id[i][0]] == id[i][0]) {
            ans *= 10;
            ans %= mod;
        }
    }
//  for (register int i = 1; i <= 18; i++) printf("%d ",base[i]);
//  return 0;
    printf("%lld\n", ans%mod);
    return 0;
}

标签:P1525,cnt,fx,关押,int,fy,get,fa,洛谷
来源: https://www.cnblogs.com/kma093/p/10807671.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有