洛谷p1726(上白泽慧音)题解「建议收藏」

洛谷p1726(上白泽慧音)题解「建议收藏」题目:在幻想乡,上白泽慧音是以知识渊博闻名的老师

洛谷p1726(上白泽慧音)题解「建议收藏」"

题目:
在幻想乡,上白泽慧音是以知识渊博闻名的老师。春雪异变导致人间之里的很多道路都被大雪堵塞,使有的学生不能顺利地到达慧音所在的村庄。因此慧音决定换一个能够聚集最多人数的村庄作为新的教学地点。人间之里由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

#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=50001;
int begin[maxn],next[maxn],to[maxn];
int tot,n,m;
int dfsn[maxn],low[maxn];
int stack_[maxn];
int put[maxn];
void add_(int x,int y){
    to[++tot]=y;
    next[tot]=begin[x];
    begin[x]=tot;
}

int find_(int x){
    for(register int i=1;i<=stack_[0];++i)
        if(stack_[i]==x)return true;
    return false;
}

void tarjan(int u){
    dfsn[u]=low[u]=++tot;
    stack_[++stack_[0]]=u;
    for(register int i=begin[u];i;i=next[i]){
        int v=to[i];
        if(!dfsn[v]){
            tarjan(v);
            low[u]=min(low[u],low[v]);
        }
            else if(find_(v))low[u]=min(low[u],dfsn[v]);
    }
    if(low[u]==dfsn[u]){
        int flag=0;
        register int sum=1;
        for(register int i=stack_[0];stack_[i]!=u;--i)++sum;
        if(sum>put[0])flag=1;
        {
            if(flag==1)put[0]=0;
            while(stack_[stack_[0]]!=u){
                if(flag==1)put[++put[0]]=stack_[stack_[0]];
                --stack_[0];
            }
            if(flag==1)put[++put[0]]=stack_[stack_[0]];
            --stack_[0];
        }	
    }
}

int main(){
    scanf("%d %d",&n,&m);
    register int i;
    for(i=1;i<=m;++i){
        int a,b,c;
        scanf("%d %d %d",&a,&b,&c);
        if(c==1)
            add_(a,b);
        if(c==2){
            add_(a,b);add_(b,a);	
        }
    }
    for(i=1;i<=n;++i){
        if(!dfsn[i])tarjan(i);
    }
    sort(put+1,put+put[0]+1);
    printf("%d\n",put[0]);
    for(i=1;i<=put[0];++i)
        printf("%d ",put[i]);
    return 0;
}

今天的文章洛谷p1726(上白泽慧音)题解「建议收藏」分享到此就结束了,感谢您的阅读。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/62533.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注