上白泽慧音(tarjan,图的染色)
題目描述
在幻想鄉(xiāng),上白澤慧音是以知識(shí)淵博聞名的老師。春雪異變導(dǎo)致人間之里的很多道路都被大雪堵塞,使有的學(xué)生不能順利地到達(dá)慧音所在的村莊。因此慧音決定換一個(gè)能夠聚集最多人數(shù)的村莊作為新的教學(xué)地點(diǎn)。人間之里由N個(gè)村莊(編號(hào)為1..N)和M條道路組成,道路分為兩種一種為單向通行的,一種為雙向通行的,分別用1和2來(lái)標(biāo)記。如果存在由村莊A到達(dá)村莊B的通路,那么我們認(rèn)為可以從村莊A到達(dá)村莊B,記為(A,B)。當(dāng)(A,B)和(B,A)同時(shí)滿足時(shí),我們認(rèn)為A,B是絕對(duì)連通的,記為<A,B>。絕對(duì)連通區(qū)域是指一個(gè)村莊的集合,在這個(gè)集合中任意兩個(gè)村莊X,Y都滿足<X,Y>。現(xiàn)在你的任務(wù)是,找出最大的絕對(duì)連通區(qū)域,并將這個(gè)絕對(duì)連通區(qū)域的村莊按編號(hào)依次輸出。若存在兩個(gè)最大的,輸出字典序最小的,比如當(dāng)存在1,3,4和2,5,6這兩個(gè)最大連通區(qū)域時(shí),輸出的是1,3,4。
輸入輸出格式
輸入格式:
第1行:兩個(gè)正整數(shù)N,M
第2..M+1行:每行三個(gè)正整數(shù)a,b,t, t = 1表示存在從村莊a到b的單向道路,t = 2表示村莊a,b之間存在雙向通行的道路。保證每條道路只出現(xiàn)一次。
輸出格式:
第1行: 1個(gè)整數(shù),表示最大的絕對(duì)連通區(qū)域包含的村莊個(gè)數(shù)。
第2行:若干個(gè)整數(shù),依次輸出最大的絕對(duì)連通區(qū)域所包含的村莊編號(hào)。
思路:
顯然,有題可得,這是讓我們求一個(gè)面積最大的強(qiáng)連通分量
(如果有面積相同的情況,輸出字典序最小的)
我們自然可以用tarjan縮點(diǎn)
我們把舊點(diǎn)的點(diǎn)權(quán)當(dāng)作1
這樣縮完后每個(gè)新點(diǎn)就是一個(gè)強(qiáng)連通分量,點(diǎn)權(quán)就是新點(diǎn)所代表的強(qiáng)連通分量的大小
我們縮完點(diǎn)后O(n)掃一邊所有新點(diǎn),記下最大的點(diǎn)權(quán)
然后再按字典序O(n)掃一邊舊點(diǎn),記下第一個(gè)所在新點(diǎn)點(diǎn)權(quán)為最大值的舊點(diǎn)所屬新點(diǎn)的編號(hào)
再按字典序O(n)掃一邊舊點(diǎn),輸出所在新點(diǎn)為上一次操作記下的新點(diǎn)舊點(diǎn)即可
代碼:
// luogu-judger-enable-o2 #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define rij register int j #define rii register int i using namespace std; int dq[5005],sum[5005],color[5005],tot,cnt,vis[5005]; int n,m,head[5005],last[5005],sta[5005],top,bnt; int dfn[5005],low[5005],ls[5005]; struct ljb{int to,nxt; }x[100005]; void add(int from,int to) {cnt++;x[cnt].to=to;if(head[from]==0){head[from]=cnt;}else{x[last[from]].nxt=cnt;}last[from]=cnt; } void tarjan(int wz) {top++;sta[top]=wz;bnt++;low[wz]=bnt;dfn[wz]=bnt;vis[wz]=1;for(rii=head[wz];i!=0;i=x[i].nxt){int ltt=x[i].to;if(dfn[ltt]==0){tarjan(ltt);low[wz]=min(low[wz],low[ltt]);}else{if(vis[ltt]!=0){low[wz]=min(low[wz],dfn[ltt]);}}}if(dfn[wz]==low[wz]){tot++;while(sta[top+1]!=wz){color[sta[top]]=tot;sum[tot]+=dq[sta[top]];vis[sta[top]]=0;top--;}} } int main() {scanf("%d%d",&n,&m);for(rii=1;i<=n;i++){dq[i]=1;}for(rii=1;i<=m;i++){int p,from,to;scanf("%d%d%d",&from,&to,&p);if(p==2){add(to,from);}add(from,to);}for(rii=1;i<=n;i++){if(dfn[i]==0){tarjan(i);}}int maxn=0;for(rii=1;i<=n;i++){int col=color[i];if(sum[col]>maxn){maxn=sum[col];}}cout<<maxn<<endl;int pd;for(rii=1;i<=n;i++){int col=color[i];if(sum[col]==maxn){pd=col;break;}}for(rii=1;i<=n;i++){if(color[i]==pd){printf("%d ",i);}} }?
轉(zhuǎn)載于:https://www.cnblogs.com/ztz11/p/9810745.html
總結(jié)
以上是生活随笔為你收集整理的上白泽慧音(tarjan,图的染色)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: vue 本地环境API代理设置和解决跨域
- 下一篇: shell 变量相关的命令