zoukankan      html  css  js  c++  java
  • 洛谷 P1477 [NOI2008]假面舞会

    题目链接

    题目描述

    一年一度的假面舞会又开始了,栋栋也兴致勃勃的参加了今年的舞会。

    今年的面具都是主办方特别定制的。每个参加舞会的人都可以在入场时选择一 个自己喜欢的面具。每个面具都有一个编号,主办方会把此编号告诉拿该面具的人。

    为了使舞会更有神秘感,主办方把面具分为(k(k≥3))类,并使用特殊的技术将每个面具的编号标在了面具上,只有戴第(i) 类面具的人才能看到戴第(i+1) 类面具的人的编号,戴第(k) 类面具的人能看到戴第1 类面具的人的编号。

    参加舞会的人并不知道有多少类面具,但是栋栋对此却特别好奇,他想自己算出有多少类面具,于是他开始在人群中收集信息。

    栋栋收集的信息都是戴第几号面具的人看到了第几号面具的编号。如戴第2号面具的人看到了第5 号面具的编号。栋栋自己也会看到一些编号,他也会根据自己的面具编号把信息补充进去。

    由于并不是每个人都能记住自己所看到的全部编号,因此,栋栋收集的信 息不能保证其完整性。现在请你计算,按照栋栋目前得到的信息,至多和至少有多少类面具。由于主办方已经声明了(k≥3),所以你必须将这条信息也考虑进去。

    输入输出格式
    输入格式:

    第一行包含两个整数n, m,用一个空格分隔,n 表示主办方总共准备了多少个面具,m 表示栋栋收集了多少条信息。接下来m 行,每行为两个用空格分开的整数a, b,表示戴第a 号面具的人看到了第b 号面具的编号。相同的数对a, b 在输入文件中可能出现多次。

    输出格式:

    包含两个数,第一个数为最大可能的面具类数,第二个数为最小可能的面具类数。如果无法将所有的面具分为至少3 类,使得这些信息都满足,则认为栋栋收集的信息有错误,输出两个-1。

    输入样例#1

    6 5
    1 2
    2 3
    3 4
    4 1
    3 5

    输出样例#1:

    4 4

    输入样例#2:

    3 3
    1 2
    2 1
    2 3

    输出样例#2:

    -1 -1

    说明

    50%的数据,满足(n ≤ 300, m ≤ 1000)

    100%的数据,满足(n ≤ 100000, m ≤ 1000000)

    题解

    显然,
    ①如果有多个点指向同一个点,那么他们属于同一类别。
    ②一个点看到的所有点是一个种类。

    那么我们可以吧以上情况缩一下,具体就是给每个关系构一条-1的反边

    然后就在这条图上操作
    可以发现图上会有环和链

    对于链,不管(k)取多少都可以满足

    对于环,(k)满足是环上点数的约数

    那么有环的情况,最大就为所以环点数的(gcd)
    没环就是所有链的长度和

    对于最小的(k), 答案为最小的(k(k geq 3))满足 (k)为所有环大小的约数
    如果没环,答案为(3)

    Code

    #include<bits/stdc++.h>
    #define LL long long
    #define RG register
    using namespace std;
    
    inline int gi() {
        int f = 1, s = 0;
        char c = getchar();
        while (c != '-' && (c < '0' || c > '9')) c = getchar();
        if (c == '-') f = -1, c = getchar();
        while (c >= '0' && c <= '9') s = s*10+c-'0', c = getchar();
        return f == 1 ? s : -s;
    }
    const int N = 100010;
    struct node {
    	int to, next, w;
    }g[2000010];
    int last[N], gl;
    void add(int x, int y, int z) {
    	g[++gl] = (node) {y, last[x], z};
    	last[x] = gl;
    	return ;
    }
    
    inline int gcd(int a, int b) {
    	return !b ? a : gcd(b, a%b);
    }
    
    int cnt, Max[N], Min[N], dis[N], ans1, ans2;
    bool flag[N];
    void dfs(int u) {
    	flag[u] = 1;
    	Max[cnt] = max(Max[cnt], dis[u]);
    	Min[cnt] = min(Min[cnt], dis[u]);
    	for (int i = last[u]; i; i = g[i].next) {
    		int v = g[i].to;
    		if (!flag[v]) {
    			dis[v] = dis[u]+g[i].w;
    			dfs(v);
    		}
    		else {
    			if (!ans1) ans1 = abs(dis[u]+g[i].w-dis[v]);
    			else ans1 =P3616 富金森林公园 gcd(ans1, abs(dis[u]+g[i].w-dis[v]));
    		}
    	}
    	return ;
    }
    
    int main() {
    	int n = gi(), m = gi();
    	for (int i = 1; i <= m; i++) {
    		int u = gi(), v = gi();
    		add(u, v, 1); add(v, u, -1);
    	}
    	memset(Min, 127/3, sizeof(Min));
    	for (int i = 1; i <= n; i++)
    		if (!flag[i])
    			++cnt, dfs(i);
    	if (!ans1) {
    		for (int i = 1; i <= cnt; i++)
    			ans1 += Max[i]-Min[i]+1;
    		if (ans1 < 3)
    			printf("-1 -1
    ");
    		else printf("%d 3
    ", ans1);
    		return 0;
    	}
    	if (ans1 < 3) {
    		printf("-1 -1
    ");
    		return 0;
    	}
    	printf("%d ", ans1);
    	for (int i = 3; i <= ans1; i++)
    		if (ans1 % i == 0) {
    			printf("%d
    ", i);
    			return 0;
    		}
        return 0;
    }
    
  • 相关阅读:
    【死磕Java并发】—–J.U.C之AQS(一篇就够了)
    Java并发包基石-AQS详解
    java并发api总结
    用Java对CSV文件进行读写操作
    多线程批量检测未注册域名
    RSA公钥、私钥、签名和验签
    ASCII,Unicode和UTF-8终于找到一个能完全搞清楚的文章了
    Java 常用工具类---- 各种字符集编码判断与转换
    JavaMail| JavaMail配置属性
    QT下的几种透明效果(QPalette背景白色,窗口设置setWindowOpacity,QPainter使用Clear模式绘图)
  • 原文地址:https://www.cnblogs.com/zzy2005/p/9861262.html
Copyright © 2011-2022 走看看