点双/边双 连通分量

发布时间 2023-09-25 22:18:58作者: towboat

 

点双

  找到割点后 一直退栈 

http://ybt.ssoier.cn:8088/problem_show.php?pid=1521

include <iostream>
#include <algorithm>
#include <cmath>
#include <vector>
#include<stack>
using namespace std ;

 const int N=502;
 #define int long long
 
 vector<int> g[N],bk[N];
 stack<int> st; 
 int n,m,low[N],dfn[N],cut[N],pool,tot;
 
 void add(int x,int y){
 	g[x].push_back(y);
 }
 void init(){
 	    int i,x,y;
		for(i=0;i<N;i++) g[i].clear(),cut[i]=dfn[i]=low[i]=0; 
		pool=tot= 0;
		while(!st.empty()) st.pop();
		
		for(i=1;i<=m;i++){
			cin>>x>>y;
			n=max(n,max(x,y));
			add(x,y),add(y,x);
		}	
}
 void dfs(int x,int fa){
 	dfn[x]=low[x]=++pool; st.push(x);
	  
	  int c=0;
 	for(int y:g[x]){
	  if(!dfn[y]){
	  	c++;
	    dfs(y,x),low[x]=min(low[x],low[y]);
		if(!fa&&c>1||fa&&dfn[x]<=low[y]) cut[x]=1;
		
		if(dfn[x]<=low[y]){
			tot++; bk[tot].clear();
			
		    while(1){
		   	  int t=st.top(); st.pop(); 
		   	  bk[tot].push_back(t);
		   	  if(t==y) break;
		    } 
		   bk[tot].push_back(x);
		}
	  } 
	  else low[x]=min(low[x],dfn[y]);
	}
 }
 

 void sov(){
 	for(int i=1;i<=n;i++) 
			if(!dfn[i]) dfs(i,0); 
 	int c1=0,c2=1;
 	
 	for(int i=1;i<=tot;i++){
 		int cnt=0, siz=bk[i].size(); 
 		
	 	for(int x:bk[i])
	 		if(cut[x]) cnt++;
		  
	  	if(cnt==0) c1+=2, c2=c2*siz*(siz-1)/2;
	 	if(cnt==1) c1++, c2=c2*(siz-1);
	}
   cout<<c1<<' '<<c2<<'\n'; 
 }
signed main(){
 	int T=0;
 	while(cin>>m&&m){
 		init(); 
		cout<<"Case "<<++T<<": ";
		sov();
	}
 }

 

边双

 https://vjudge.csgrandeur.cn/problem/POJ-3352

#include <iostream>
#include <algorithm>
#include <cmath>
#include <vector>
#include<stack>
using namespace std ;

 const int N=1e5;
 #define int long long
 
 vector<int> g[N];

 int n,m,low[N],dfn[N],pool;
 
 void add(int x,int y){ g[x].push_back(y); }
 
 void dfs(int x,int fa){
 	dfn[x]=low[x]=++pool; 
	  
 	for(int i=0;i<g[x].size();i++){
 		  int y =g[x][i]; if(fa==y) continue ;
		  if(!dfn[y]){
		  	 dfs(y,x) ; low[x] =min(low[x],low[y]) ;
		  } 
		  else if(dfn[x]>dfn[y]) low[x]=min(low[x],dfn[y]);
	}
 }
 
 
int in[N] ;
 void sov(){
 	for(int i=1;i<=n;i++) 
		if(!dfn[i]) dfs(i,0); 
 	
 	for(int i=1;i<=n;i++)
	 	 for(int e=0;e<g[i].size();e++){
	 	 	int y= g[i][e] ;
	 	 	if(low[i]!=low[y]) in[low[y]]++;
	 	 }
	 	
	int cnt=0 ;
	for(int i=1;i<=n;i++)
		if(in[i]==1) cnt++ ;
	cout <<(cnt+1)/2<<endl;
 }
signed main(){
		cin>>n>>m;
		for(int x,y,i=1;i<=m;i++){
			cin>>x>>y;
			add(x,y),add(y,x);
		}	
		sov() ;
 }