简介:用tarjan找割点,当dfn[u]<=low[v]时,证明当前的u为割点,注意割点可能存在于多个点双连通分量中,所以存点的时候要格外注意。如果当前遍历到的v已在栈中,可以用dfn[v]更新low[u]。
ps:两点一边的图也为一个点双连通分量。
模板:
将下面的代码略微改动即可
例题:
hduoj3394 Railway
1 #include<iostream> 2 #include<cstdio> 3 #include<cctype> 4 #include<vector> 5 #define numm ch-48 6 #define pd putchar(' ') 7 #define pn putchar('\n') 8 #define pb push_back 9 #define debug(args...) cout<<#args<<"->"<<args<<endl 10 #define bug cout<<"************" 11 using namespace std; 12 template <typename T> 13 void read(T &res) { 14 bool flag=false;char ch; 15 while(!isdigit(ch=getchar())) (ch=='-')&&(flag=true); 16 for(res=numm;isdigit(ch=getchar());res=(res<<1)+(res<<3)+numm); 17 flag&&(res=-res); 18 } 19 template <typename T> 20 void write(T x) { 21 if(x<0) putchar('-'),x=-x; 22 if(x>9) write(x/10); 23 putchar(x%10+'0'); 24 } 25 typedef long long ll; 26 const int maxn=10010; 27 const int maxm=200010; 28 const ll mod=1e9+7; 29 int low[maxn],dfn[maxn],sta[maxn],vis[maxn],sum,head[maxn],f[maxn]; 30 int u[maxm],v[maxm]; 31 int n,m,lay,ans1,ans2,cnt; 32 struct node { 33 int net,v; 34 node(){} 35 node(int v,int net):v(v),net(net){} 36 }e[maxm]; 37 void add(int u,int v) { 38 e[++cnt]=node(v,head[u]); 39 head[u]=cnt; 40 } 41 void getnode(int sccnum) { 42 int cnt=0; 43 for(int i=1;i<=m;i++) 44 if(f[u[i]]==sccnum&&f[u[i]]==f[v[i]]) 45 cnt++; 46 if(cnt>=sum) ans1+=cnt; ///当中没有桥 47 if(cnt>sum) ans2+=cnt; 48 } 49 void tarjan(int x,int &sccnum) { 50 sta[++cnt]=x; 51 low[x]=lay; 52 dfn[x]=lay++; 53 vis[x]=1; 54 for(int i=head[x];~i;i=e[i].net) { 55 int v=e[i].v; 56 if(!dfn[v]) { 57 tarjan(v,sccnum); 58 low[x]=min(low[x],low[v]); 59 if(dfn[x]<=low[v]) { ///x是割点 60 ++sccnum; 61 sum=0; ///点的数量 62 do { 63 f[sta[cnt]]=sccnum; 64 vis[sta[cnt]]=2; 65 sum++; 66 }while(sta[cnt--]!=v); 67 f[x]=sccnum,sum++; 68 getnode(sccnum); 69 } 70 } 71 else if(vis[v]==1) low[x]=min(low[x],dfn[v]); 72 } 73 } 74 int main() 75 { 76 77 while(scanf("%d%d",&n,&m)!=EOF&&(n+m)) { 78 ans1=ans2=0; 79 for(int i=0;i<n;i++) 80 head[i]=-1,vis[i]=0,dfn[i]=0,f[i]=0; 81 cnt=0; 82 for(int i=1;i<=m;i++) { 83 read(u[i]),read(v[i]); 84 add(u[i],v[i]); 85 add(v[i],u[i]); 86 } 87 lay=1,cnt=0; 88 int sccnum=0; 89 for(int i=0;i<n;i++) 90 if(!vis[i]) tarjan(i,sccnum); 91 write(m-ans1),pd,write(ans2);pn; 92 } 93 return 0; 94 }