洛谷P1726 上白泽慧音

本文介绍了一道名为P1726上白泽慧音的图论题目的解题思路及实现过程。题目背景设置在幻想乡,要求找到最大的绝对连通区域并输出。通过使用Tarjan算法求出强连通分量,最终确定最大连通区域。

P1726 上白泽慧音

    • 124通过
    • 343提交
  • 题目提供者yeszy
  • 标签图论
  • 难度提高+/省选-

提交该题 讨论 题解 记录

最新讨论

  • 给两组数据吧!

题目描述

在幻想乡,上白泽慧音是以知识渊博闻名的老师。春雪异变导致人间之里的很多道路都被大雪堵塞,使有的学生不能顺利地到达慧音所在的村庄。因此慧音决定换一个能够聚集最多人数的村庄作为新的教学地点。人间之里由N个村庄(编号为1..N)和M条道路组成,道路分为两种一种为单向通行的,一种为双向通行的,分别用1和2来标记。如果存在由村庄A到达村庄B的通路,那么我们认为可以从村庄A到达村庄B,记为(A,B)。当(A,B)和(B,A)同时满足时,我们认为A,B是绝对连通的,记为<A,B>。绝对连通区域是指一个村庄的集合,在这个集合中任意两个村庄X,Y都满足<X,Y>。现在你的任务是,找出最大的绝对连通区域,并将这个绝对连通区域的村庄按编号依次输出。若存在两个最大的,输出字典序最小的,比如当存在1,3,4和2,5,6这两个最大连通区域时,输出的是1,3,4。

输入输出格式

输入格式:

 

第1行:两个正整数N,M

第2..M+1行:每行三个正整数a,b,t, t = 1表示存在从村庄a到b的单向道路,t = 2表示村庄a,b之间存在双向通行的道路。保证每条道路只出现一次。

 

输出格式:

 

第1行: 1个整数,表示最大的绝对连通区域包含的村庄个数。

第2行:若干个整数,依次输出最大的绝对连通区域所包含的村庄编号。

 

输入输出样例

输入样例#1:
5 5
1 2 1
1 3 2
2 4 2
5 1 2
3 5 1
输出样例#1:
3
1 3 5

说明

对于60%的数据:N <= 200且M <= 10,000

对于100%的数据:N <= 5,000且M <= 50,000

分析:看到这道题以为是强连通分量,越看越像,最后发现这就是强连通分量,直接一个tarjan算法求出强连通分量后,枚举每个元素,累加强连通分量的计数器,并更新最小值即可.关于强连通分量的讲解可以在我的另一篇博文洛谷间谍网络的题解中查看.

#include <cstdio>
#include <stack>
#include <cstring>
#include <iostream>
#include <algorithm>

const int maxn = 10010, maxm = 50010;

using namespace std;

int n, m,scc_cnt,ans,k,sccsum[maxn],sccmin[maxn],dfs_clock,sccno[maxn],pre[maxn],lowlink[maxn],head[maxn],nextt[maxm*2],to[maxm * 2],tot;

stack<int> S;

void add(int u, int v)
{
    tot++;
    to[tot] = v;
    nextt[tot] = head[u];
    head[u] = tot;
}

void dfs(int u) {
    pre[u] = lowlink[u] = dfs_clock++;
    S.push(u);
     for (int i = head[u]; i; i =nextt[i]) {
                 int v = to[i];
                 if (!pre[v]) {
                         dfs(v);
                         lowlink[u] = min(lowlink[u], lowlink[v]);
            
        }
                 else if (!sccno[v]) {
                         lowlink[u] = min(pre[v], lowlink[u]);
            
        }
        
    }
         if (pre[u] == lowlink[u]) {
                 scc_cnt++;
                for (;;) {
                         int v = S.top(); S.pop();
                         sccno[v] = scc_cnt;
                         if (v == u) break;
            
        }
        
    }
    
}


int main()
{
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= m; i++)
    {
        int u, v, w;
        scanf("%d%d%d", &u, &v, &w);
        if (w == 1)
            add(u, v);
        else
        {
            add(u, v);
            add(v, u);
        }
    }
    for (int i = 1; i <= n; i++)
        if (!pre[i])
            dfs(i);
    for (int i = 1; i <= n; i++)
    {
        sccsum[sccno[i]]++;
        if (!sccmin[sccno[i]])
            sccmin[sccno[i]] = i;
    }
    for (int i = 1; i <= scc_cnt; i++)
    {
        if (sccsum[i] > ans || sccsum[i] == ans && sccmin[i] < sccmin[k])
        {
            ans = sccsum[i];
            k = i;
        }
    }
    printf("%d\n", ans);
    for (int i = 1; i <= n; i++)
        if (sccno[i] == k)
            printf("%d ", i);
    printf("\n");

    return 0;
}

 

转载于:https://www.cnblogs.com/zbtrs/p/5811368.html

改一下题面,标题自拟,要求把主角改成数学老师胡特。胡特精通数学领域,而且经常给同学们打鸡血 题面: ## 题目背景 上白泽在给雾之湖的妖精们讲课。 某天,在上数学课时,提到了一种非常有趣的记号:**高德纳箭号表示法**。它可以用来描述非常巨大的数字。~~比如紫的年龄。~~ 对于非负整数 $a, b$ 和正整数 $n$,高德纳箭号表示法的定义为: $$a \uparrow^n b = \begin{cases} 1\ (b = 0) \\ a^b\ (n = 1\ \operatorname{and}\ b > 0) \\ a \uparrow^{n - 1} (a \uparrow^n (b - 1))\ (n > 1\ \operatorname{and}\ b > 0) \end{cases}$$ 一些简单的例子: - $2 \uparrow 31 = 2^{31} = 2147483648$ - $2 \uparrow \uparrow 4 = 2^{2^{2^2}} = 2^{2^4} = 2^{16} = 65536$ 注: 1. $a \uparrow b$ 与 $a \uparrow^1 b$ 相同; 2. $a \uparrow \uparrow b$ 与 $a \uparrow^2 b$ 相同; 3. 请注意幂运算的顺序。 ## 题目描述 希望琪露诺解决以下关于 $x$ 的方程: $$a \uparrow^n x \equiv b \pmod p$$ 其中,$a, n, b, p$ 为已知的常数,$x$ 为未知数。 琪露诺被高德纳箭号表示法搞得云里雾里的,但是她不想被头槌。你能帮帮她吗? ## 输入格式 **本题有多组测试数据。** 第一行,一个整数 $T$,表示数据组数。 对于每组数据: 一行,四个整数 $a, n, b, p$。 ## 输出格式 对于每组数据,输出一行,一个整数,如果原方程有解,输出该方程的最小非负整数解;否则,输出 $-1$。 ## 输入输出样例 #1 ### 输入 #1 ``` 3 2 1 1 3 3 1 2 7 7 1 2 4 ``` ### 输出 #1 ``` 0 2 -1 ``` ## 输入输出样例 #2 ### 输入 #2 ``` 3 2 2 4 7 3 2 4 6 5 2 1 3 ``` ### 输出 #2 ``` 2 -1 0 ``` ## 输入输出样例 #3 ### 输入 #3 ``` 3 4 3 5 8 2 3 9 11 6 3 1 5 ``` ### 输出 #3 ``` -1 3 0 ``` ## 说明/提示 **本题开启捆绑测试。** | Subtask | $n$ | $p$ | $T$ | 分值 | 时限 | | :------: | :------: | :------: | :------: | :------: | :------: | | $1$ | $n = 1$ | $2 \leq p \leq 10^9$ 且 $p$ 为质数 | $1 \leq T \leq 100$ | $15 \operatorname{pts}$ | $2.00 \operatorname{s}$ | | $2$ | $n = 2$ | 无特殊限制 | $1 \leq T \leq 5 \times 10^3$ | $25 \operatorname{pts}$ | $1.00 \operatorname{s}$ | | $3$ | $n = 3$ | 无特殊限制 | 无特殊限制 | $60 \operatorname{pts}$ | $2.00 \operatorname{s}$ | 对于 $100\%$ 的数据,$1 \leq a \leq 10^9$,$1 \leq n \leq 3$,$0 \leq b < p \leq 10^9$,$1 \leq T \leq 2 \times 10^4$。
最新发布
09-06
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值