D.Router Mesh
Router Mesh
https://ac.nowcoder.com/acm/contest/7501/D
题意:
模板题,求图中每个割点能把网络分成几个点双连通分量(不是割点就输出他有几块即可)。
题解:
跟POJ 的SPF很像
这题用Tarjan来求,首先我们需要统计出来具体有几个连通块。
对于每个连通块,我们需要判断这个割点去掉后,这幅图会被分成几块?
这个其实很简单,只需要更改一下判断这个点是否为割点即可。
每被判断成一个割点,那么这个割点++。
注意特判根节点! 看看它有几个不相连的子树
num[]代表的是 从这个点分支出去,有几个不相连的子树
到最后的时候要进行num[i]--,是因为他是头节点。(画个图理解一下)
num[i]--;
/*Keep on going Never give up*/ //#pragma GCC optimize(3,"Ofast","inline") #include<bits/stdc++.h> #define int long long #define endl '\n' #define Accepted 0 #define AK main() #define I_can signed using namespace std; const int maxn =3e5+10; const int MaxN = 0x3f3f3f3f; const int MinN = 0xc0c0c00c; typedef long long ll; const int inf=0x3f3f3f3f; const ll mod=1e9+7; using namespace std; vector<int> edge[maxn]; int n,m; int low[maxn]; int num[maxn],dfn[maxn]; bool visited[maxn]; int cnt,top; void dfs(int u,int fa){ visited[u]=true; low[u]=dfn[u]=++cnt; int ch=0; for(int i=0;i<edge[u].size();i++){ int v=edge[u][i]; if(!visited[v]){ ch++; dfs(v,u); low[u]=min(low[v],low[u]); if(low[v]>=dfn[u]) num[u]++; } else if(dfn[v]<dfn[u]&&v!=fa){ low[u]=min(dfn[v],low[u]); } } // if(u==top&&ch>=1){ // num[u]=ch; // } } I_can AK { //freopen("in.txt","r",stdin); ios::sync_with_stdio(false); memset(visited,false,sizeof visited); cin>>n>>m; for(int i=0;i<m;i++){ int u,v; cin>>u>>v; edge[u].push_back(v); edge[v].push_back(u); } //dfs(1,-1); int ans=0; //cout<<visited[1]<<endl; for(int i=1;i<=n;i++){ if(!visited[i]){ ans++; //cout<<i<<endl; top=i; dfs(i,-1); num[i]--; } } //cout<<ans<<endl; //cout<<num[1]<<endl; for(int i=1;i<=n;i++){ cout<<num[i]+ans<<" "; } return 0; }
题解 文章被收录于专栏
主要写一些题目的题解