Kuangbin带你飞-专题九连通图
目录
1.POJ1236 Network of Schools(Tarjan缩点)
2.UVA315 Network(Tarjan求割点)
POJ1236 Network of Schools(Tarjan缩点)
题意:
给一张有向图,问你至少要选多少点,从这些点出发可以遍历整个图,最少要加多少条边才能使整个图联通
思路:
先对整个图进行缩点,然后统计出缩点之后每个点的出度与入度
第一个答案就为入度为0的点,第二个答案就为出度为0跟入度为0的点个数的最大值,注意要特判缩点之后点为1的情况
#include<iostream> #include<algorithm> #include<vector> #include<cstdio> using namespace std; const int maxn=105; vector<int> a[maxn]; int dfs[maxn],low[maxn],s[maxn],n,flag[maxn],tot,cnt[maxn],t,k,color[maxn]; int in[maxn],out[maxn]; void tarjan(int x) { dfs[x]=low[x]=++tot; s[++k]=x; flag[x]=1; for(int i=0;i<a[x].size();i++){ if(!dfs[a[x][i]]){ tarjan(a[x][i]); low[x]=min(low[x],low[a[x][i]]); } else if(flag[a[x][i]]) low[x]=min(low[x],dfs[a[x][i]]); } if(dfs[x]==low[x]){ t++; do{ color[s[k]]=t,cnt[t]++; flag[s[k--]]=0; }while(x!=s[k+1]); } } int main() { scanf("%d",&n); for(int i=1;i<=n;i++){ int temp; while(scanf("%d",&temp)&&temp) a[i].push_back(temp); } for(int i=1;i<=n;i++){ if(!dfs[i]) tarjan(i); } for(int i=1;i<=n;i++){ for(int j=0;j<a[i].size();j++){ if(color[i]!=color[a[i][j]]){ in[color[a[i][j]]]++; out[color[i]]++; } } } int ans1=0,ans2=0; for(int i=1;i<=t;i++){ if(in[i]==0) ans1++; if(out[i]==0) ans2++; } cout<<ans1<<endl; if(t==1) cout<<0; else cout<<max(ans1,ans2)<<endl; }
UVA315 Network(Tarjan求割点)
题意:
求割点数量
#include<iostream> #include<algorithm> #include<vector> #include<cstdio> #include<cstring> #include<sstream> using namespace std; typedef long long ll; const int maxn=105+10; vector<int> a[maxn]; int low[maxn],dfs[maxn],tot,ans,cnt[maxn]; void tarjan(int u,int fa) { dfs[u]=low[u]=++tot; int son=0; for(int i=0;i<a[u].size();i++){ int v=a[u][i]; if(!dfs[v]){ tarjan(v,fa); low[u]=min(low[u],low[v]); if(low[v]>=dfs[u]&&u!=fa) cnt[u]=1; if(u==fa) son++; } low[u]=min(low[u],dfs[v]); } if(u==fa&&son>1) cnt[fa]=1; } int main() { int n,temp; while(scanf("%d",&n)&&n){ for(int i=1;i<=n;i++){ a[i].clear(); dfs[i]=low[i]=cnt[i]=0; } tot=0; ans=0; string s; while(getline(cin,s)){ if(s=="0")break; istringstream ss(s); int b; ss>>b; int t; while(ss>>t){ a[b].push_back(t); a[t].push_back(b); } } for(int i=1;i<=n;i++){ if(!dfs[i]) tarjan(i,i); } for(int i=1;i<=n;i++) if(cnt[i]) ans++; cout<<ans<<endl; } return 0; }