1. 程式人生 > >P1726 上白澤慧音

P1726 上白澤慧音

不能 我們 題目 編號 int bsp als 新的 min

洛谷—— 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

思路:

一個tarjan板子題,但要在裏面進行一些修改。

我們不需要統計每一個點在哪個強連通分量裏,只需要把每個強連通分量裏的點都統計下來,然後在比較每一個強連通分量的大小,我們不是在統計點的時候用了一個sum來統計點的數據嗎,再用一個ans,他兩個進行比較,把大的強連通分量設成ans2,最後輸出時只輸出ans2

代碼:

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include
<algorithm> #define N 50001 using namespace std; bool vis[N]; int n,m,a,b,c,sum,top,tot,ans,ttime,maxn; int dfn[N],low[N],col[N],ans1[N],ans2[N],head[N],stack[N]; inline int read() { int x=0,f=1; char ch=getchar(); while(ch<0||ch>9){if(ch==-) f=-1; ch=getchar();} while(ch>=0&&ch<=9){x=x*10+ch-0; ch=getchar();} return x*f; } struct Edge { int from,next,to; }edge[N<<1]; inline void add(int x,int y) { tot++; edge[tot].to=y; edge[tot].next=head[x]; head[x]=tot; } void tarjan(int now) { dfn[now]=low[now]=++ttime; stack[++top]=now;vis[now]=true; for(int i=head[now];i;i=edge[i].next) { int t=edge[i].to; if(vis[t]) low[now]=min(low[now],dfn[t]); else if(!dfn[t]) tarjan(t),low[now]=min(low[now],low[t]); } if(low[now]==dfn[now]) { sum=0;ans1[++sum]=now; for(;stack[top]!=now;top--) { ans1[++sum]=stack[top]; vis[stack[top]]=false; } vis[now]=false; top--; if(sum>ans) { memset(ans2,0,sizeof(ans2)); ans=sum; for(int i=1;i<=sum;i++) ans2[i]=ans1[i]; sort(ans2+1,ans2+1+ans); } if(sum==ans) { sort(ans1+1,ans1+1+ans); if(ans1[1]<ans2[1]) { memset(ans2,0,sizeof(ans2)); for(int i=1;i<=ans;i++) ans2[i]=ans1[i]; } } } } int main() { n=read(),m=read(); for(int i=1;i<=m;i++) { a=read(),b=read(),c=read(); if(c==1) add(a,b); else add(a,b),add(b,a); } for(int i=1;i<=n;i++) if(!dfn[i]) tarjan(i); printf("%d\n",ans); for(int i=1;i<=n;i++) if(ans2[i]) printf("%d ",ans2[i]); return 0; }

P1726 上白澤慧音