日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

CodeForces 1213F (强联通分量分解+拓扑排序)

發布時間:2024/9/15 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 CodeForces 1213F (强联通分量分解+拓扑排序) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

? ? ? ??傳送門

?題意

給你兩個數組 p,q ,分別存放 1~n 的某個全排列;

讓你根據這兩個數組構造一個字符串 S,要求:

(1)$\forall i \in [1,n-1],S_{pi}\leq S _{pi+1}? ,\forall i \in [1,n-1],S_{qi} \leq S _{qi+1}$

(2)字符串 S 至少包含 k 個不同的小寫字母;

?思路

類似于牛客第五場的H

不過由于這個不知道字母是什么,需要利用強聯通分解,

把屬于同一個強聯通塊的位置置于同一個字母,

然后根據前后關系建圖連邊

?代碼

1 #include<bits/stdc++.h> 2 using namespace std; 3 #define mem(a,b) memset(a,b,sizeof a) 4 const int maxn=2e5+5; 5 int n,m; 6 int a[maxn]; 7 struct Edge 8 { 9 int to,next; 10 }G[maxn*10]; 11 int head[maxn],cnt; 12 void addEdge(int u,int v) 13 { 14 G[++cnt].to=v; 15 G[cnt].next=head[u]; 16 head[u]=cnt; 17 } 18 19 int col[maxn]; 20 struct SCC///強聯通分量分解 21 { 22 bool vis[maxn]; 23 vector<int> vs; 24 25 void DFS(int u) 26 { 27 vis[u]=true; 28 for(int i=head[u];i;i=G[i].next) 29 { 30 int v=G[i].to; 31 if(!(i&1)||vis[v]) 32 continue; 33 DFS(v); 34 } 35 vs.push_back(u); 36 } 37 38 void REDFS(int u,int k) 39 { 40 vis[u]=true; 41 col[u]=k; 42 for(int i=head[u];i;i=G[i].next) 43 { 44 int v=G[i].to; 45 if((i&1)||vis[v]) 46 continue; 47 REDFS(v,k); 48 } 49 } 50 51 int scc() 52 { 53 vs.clear(); 54 mem(vis,false); 55 for(int i=1;i<=n;i++) 56 if(!vis[i]) 57 DFS(i); 58 59 mem(vis,false); 60 int k=0; 61 for(int i=vs.size()-1;i>=0;i--) 62 if(!vis[vs[i]]) 63 REDFS(vs[i],++k); 64 65 return k; 66 } 67 }_scc; 68 69 70 Edge newG[maxn*10]; 71 int head2[maxn]; 72 void addnew(int u,int v) 73 { 74 newG[++cnt].to=v; 75 newG[cnt].next=head2[u]; 76 head2[u]=cnt; 77 } 78 int Indu[maxn]; 79 char ch[maxn]; 80 queue<int >q; 81 void topsort(int k)///拓撲排序 82 { 83 while(!q.empty()) 84 q.pop(); 85 for(int i=1;i<=k;i++) 86 if(!Indu[i]) 87 q.push(i); 88 89 int now=0; 90 while(!q.empty()) 91 { 92 int u=q.front(); 93 ch[u]='a'+now; 94 ///>=m個不同字母,那就正好m個,后面的都置為同一個 95 if(now<m-1) 96 now++; 97 q.pop(); 98 for(int i=head2[u];i;i=newG[i].next) 99 { 100 int v=newG[i].to; 101 Indu[v]--; 102 if(!Indu[v]) 103 q.push(v); 104 } 105 } 106 } 107 int main() 108 { 109 cin>>n>>m; 110 for(int i=1;i<=2;i++) 111 { 112 for(int j=1;j<=n;j++) 113 cin>>a[j]; 114 for(int j=1;j<=n-1;j++) 115 { 116 addEdge(a[j],a[j+1]); 117 addEdge(a[j+1],a[j]); 118 } 119 } 120 int k=_scc.scc(); 121 if(k<m) 122 puts("NO"); 123 else 124 { 125 puts("YES"); 126 cnt=0; 127 128 ///縮點,把每一個聯通快看做一個點 129 ///利用點col[i]之間的關系建圖,跑拓撲序 130 for(int u=1;u<=n;u++) 131 { 132 for(int i=head[u];i;i=G[i].next) 133 { 134 int v=G[i].to; 135 if(!(i&1)||col[u]==col[v]) 136 continue; 137 addnew(col[u],col[v]); 138 Indu[col[v]]++; 139 } 140 } 141 topsort(k); 142 143 for(int i=1;i<=n;i++) 144 cout<<ch[col[i]]; 145 } 146 } View Code

?

轉載于:https://www.cnblogs.com/MMMinoz/p/11479696.html

總結

以上是生活随笔為你收集整理的CodeForces 1213F (强联通分量分解+拓扑排序)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。