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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

第1节 连通性强连通、割点和桥 例题

發(fā)布時間:2023/12/3 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 第1节 连通性强连通、割点和桥 例题 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

NC15707 可達性

題目:

給出一個 0 ≤ N ≤ 105 點數(shù)、0 ≤ M ≤ 105 邊數(shù)的有向圖,
輸出一個盡可能小的點集,使得從這些點出發(fā)能夠到達任意一點,如果有多個這樣的集合,
輸出這些集合升序排序后字典序最小的。

題解:

? 先強連通縮點,變成一個有向無環(huán)圖
? 然后在所有入度為0的點集,每一個拿出編號最小的一個點
記錄縮點后的入度

for(int i=1;i<=n;i++){for(int j=head[i];j!=-1;j=edge[j].next){int u=color[i];int v=color[edge[j].v];if(u!=v)in[v]++;//記錄入度 }}

代碼:

#include<bits/stdc++.h> using namespace std; const int maxn = 1e5 + 5; const int INF = 0x3f3f3f3f; struct node {int v, next; }edge[maxn]; vector<int>p; stack <int> s; int dfn[maxn],low[maxn]; int color[maxn],in[maxn]; int tot,block; int head[maxn],pre[maxn]; int n,m,cnt,C,X; bool vis[maxn]; void add(int from, int to) {edge[++cnt].v=to;edge[cnt].next=head[from];head[from]=cnt; } void tarjan(int u) {dfn[u]=low[u]= ++tot;vis[u]=1;s.push(u);for(int i=head[u];i!=-1;i=edge[i].next) {int v=edge[i].v;if (!dfn[v]) {tarjan(v);low[u]= min(low[u],low[v]);}else if(vis[v]) low[u]=min(low[u],dfn[v]);}if (dfn[u]==low[u]) {block++;int v;do {v=s.top();s.pop();color[v]=block;pre[block]=min(v, pre[block]);//pre保存的是同強連通分量中編號最小點 vis[v]=0;} while (v!=u);} }int main() {cin>>n>>m;memset(head,-1,sizeof(head));memset(pre,INF,sizeof(pre));for(int i=0;i<m;i++){int u,v;scanf("%d%d",&u,&v);add(u,v);}for(int i=1;i<=n;i++){if(!dfn[i]) tarjan(i);}if(block==1){cout <<"1"<< endl; return 0; }for(int i=1;i<=n;i++){for(int j=head[i];j!=-1;j=edge[j].next){int u=color[i];int v=color[edge[j].v];if(u!=v)in[v]++;//記錄入度 }}for(int i=1;i<=block;i++){//此處已經(jīng)進行完壓縮,壓縮后還有block個點 if(!in[i]) //如果一個點沒有入度 p.push_back(pre[i]);}sort(p.begin(),p.end());cout<<p.size()<<endl;for(int i=0;i<p.size();i++) cout<<p[i]<< " ";cout<<endl;return 0; }

NC 19960 [HAOI2006]受歡迎的牛

題目:

? 每一頭牛的愿望就是變成一頭最受歡迎的?!,F(xiàn)在有N頭牛,給你M對整數(shù)(A,B),表示牛A認為牛B受歡迎。
? 這種關(guān)系是具有傳遞性的,如果A認為B受歡迎,B認為C受歡迎,那么牛A也認為牛C受歡迎。
? 你的任務是求出有多少頭牛被所有的牛認為是受歡迎的。

題解:

? 強連通縮點
? 唯一的一個出度為0的強連通分量
? 如果有多個出度為0的強連通分量則無解

代碼:

#include<bits/stdc++.h> using namespace std; const int maxn = 1e5 + 5; const int INF = 0x3f3f3f3f; struct node {int v, next; }edge[maxn]; vector<int>p; stack <int> s; int dfn[maxn],low[maxn]; int color[maxn],in[maxn]; int tot,block; int head[maxn],pre[maxn]; int n,m,cnt,C,X; bool vis[maxn]; void add(int from, int to) {edge[++cnt].v=to;edge[cnt].next=head[from];head[from]=cnt; } void tarjan(int u) {dfn[u]=low[u]= ++tot;vis[u]=1;s.push(u);for(int i=head[u];i!=-1;i=edge[i].next) {int v=edge[i].v;if (!dfn[v]) {tarjan(v);low[u]= min(low[u],low[v]);}else if(vis[v]) low[u]=min(low[u],dfn[v]);}if (dfn[u]==low[u]) {block++;int v;do {v=s.top();s.pop();color[v]=block;pre[block]=min(v, pre[block]);//pre保存的是同強連通分量中編號最小點 vis[v]=0;} while (v!=u);} }int main() {cin>>n>>m;memset(head,-1,sizeof(head));memset(pre,INF,sizeof(pre));for(int i=0;i<m;i++){int u,v;scanf("%d%d",&u,&v);add(u,v);}for(int i=1;i<=n;i++){if(!dfn[i]) tarjan(i);}for(int i=1;i<=n;i++){for(int j=head[i];j!=-1;j=edge[j].next){int u=color[i];int v=color[edge[j].v];if(u!=v)in[u]++; }}for(int i=1;i<=n;i++){//此處已經(jīng)進行完壓縮,壓縮后還有block個點 if(!in[color[i]]) //如果一個點沒有入度 p.push_back(pre[i]);}//sort(p.begin(),p.end());//cout<<ans;cout<<p.size()<<endl;//for(int i=0;i<p.size();i++) cout<<p[i]<< " ";//cout<<endl;return 0; }

總結(jié)

以上是生活随笔為你收集整理的第1节 连通性强连通、割点和桥 例题的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。