• UVALive 6907 Body Building tarjan


    Body Building

    题目连接:

    https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4919

    Description

    Bowo is fed up with his body shape. He has a tall posture, but he’s very skinny. No matter how much
    he eats, he never gains any weight. Even though he is a computer geek (and he loves it), he wants
    a pretty and non-geek girlfriend. Unfortunately, most girls in his surrounding do not like skinny and
    unattractive guy. Therefore, Bowo has decided to gain some muscles in his body; he joined a fitness
    club and begun to do some body building exercises.
    There are a lot of exercise equipments in a fitness club, and usually there should be weightlifting
    equipments such as barbell and dumbbell (barbell with shorter rod). Upon seeing a dumbbell, Bowo
    cannot help but imagining graphs which are similar to a dumbbell. A graph — which later referred as
    “connected component” — of N nodes is called a dumbbell if it fulfills all the following conditions:
    (i) All nodes in the graph can be partitioned into two disjoint sets P and Q which have equal size,
    i.e. N/2 nodes each.
    (ii) Both induced subgraph of P and Q are complete graphs.
    (iii) P and Q are connected by exactly one edge.
    Informally, a dumbbell is obtained by connecting two equal size complete graphs with an edge.
    For example, consider graph A in Figure 1 with 10 nodes and 21 edges. There are two disjoint
    complete graphs of size 5 which are connected by an edge. Therefore, this graph is a dumbbell. Graph
    B and C are also dumbbells. Graph D, on the other hand, is not.
    Figure 1.
    Given a graph (which might be disconnected), determine how many connected components which
    are dumbbells. A connected component is a connected subgraph which no vertex can be added and
    still be connected.

    Input

    The first line of input contains an integer T (T ≤ 50) denoting the number of cases. Each case begins
    with two integers: N and M (1 ≤ N ≤ 100; 0 ≤ M ≤ 4, 950) denoting the number of nodes and edges
    in the graph respectively. The nodes are numbered from 1 to N. The following M lines each contains
    two integer: a and b (1 ≤ a, b ≤ N; a ̸= b) representing an undirected edge connecting node a and node
    b. You are guaranteed that each pair of nodes has at most one edge in the graph.

    Output

    For each case, output ‘Case #X: Y ’, where X is the case number starts from 1 and Y is the number
    of connected components which are dumbbells for the respective case.
    Explanation for 1st sample case:
    There is only one node in the graph; a dumbbell requires at least two nodes.
    Explanation for 2nd sample case:
    Both connected components are dumbbells: {1, 2} and {3, 4}.
    Explanation for 3rd sample case:
    There are two connected components: {1, 2, 3, 4, 5, 6}, and {7, 8, 9, 10}, and both of them are
    dumbbells. The first one is dumbbell with complete graph of size 3, while the second one has size of 2.
    Explanation for 4th sample case:
    There are four connected components: {1, 2}, {3, 4}, {5, 6} and {7, 8, 9}. Only the first three are
    dumbbells.

    Sample Input

    4
    1 0
    4 2
    1 2
    3 4
    10 10
    1 2
    1 3
    2 3
    3 4
    4 5
    5 6
    4 6
    7 8
    8 9
    9 10
    9 5
    1 2
    3 4
    5 6
    7 8
    8 9

    Sample Output

    Case #1: 0
    Case #2: 2
    Case #3: 2
    Case #4: 3

    Hint

    题意

    给你个无向图,问里面有多少个子图,满足里面可以分成P,Q两个连通块,且这两个PQ都是完全图,且两个图都由一条边连接,且俩完全图的size相同。

    题解:

    跑桥,然后看看桥两边的连通块长什么样子,然后特判断一下4个点的情况……

    代码

    #include <bits/stdc++.h>
    #define rep(a,b,c) for(int (a)=(b);(a)<=(c);++(a))
    #define drep(a,b,c) for(int (a)=(b);(a)>=(c);--(a))
    #define pb push_back
    #define mp make_pair
    #define sf scanf
    #define pf printf
    #define two(x) (1<<(x))
    #define clr(x,y) memset((x),(y),sizeof((x)))
    #define dbg(x) cout << #x << "=" << x << endl;
    #define lowbit(x) ((x)&(-x))
    const int mod = 1e9 + 7;
    int mul(int x,int y){return 1LL*x*y%mod;}
    int qpow(int x , int y){int res=1;while(y){if(y&1) res=mul(res,x) ; y>>=1 ; x=mul(x,x);} return res;}
    inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f;}
    using namespace std;
    const int maxn = 100 + 15;
    int mat[maxn][maxn],N,M,vis[maxn],low[maxn],dfn[maxn],ti,label[maxn],rt,head[maxn],tot,sz[maxn];
    vector < int > block,dcc[maxn];
    stack < int > sp;
    
    struct edge{
        int v , nxt , isbrige;
    }e[maxn * maxn * 5];
    
    void dfs( int x ){
    	if( vis[x] ) return ;
    	vis[x] = 1;
    	block.pb( x );
    	for(int i = head[x] ; ~i ; i = e[i].nxt){
    		int v = e[i].v;
    		dfs( v );
    	}
    }
    
    
    void predfs( int x , int pr ){
    	dfn[x] = low[x] = ++ ti;
    	sp.push( x );
    	for(int i = head[x] ; ~i ; i = e[i].nxt){
    		int v = e[i].v;
    		if( i == ( pr ^ 1 ) ) continue;
    		if( !dfn[v] ){
    			predfs( v , i );
    			low[x] = min( low[x] , low[v] );
    			if( low[v] > dfn[x] ) e[i].isbrige = e[i ^ 1].isbrige = 1;
    		}else if( dfn[v] < dfn[x] ) low[x] = min( low[x] , dfn[v] );
    	}
    	if( low[x] == dfn[x] ){
    		int u;
    		++ rt;
    		do{
    			u = sp.top() ; sp.pop();
    			label[u] = rt;
    		}while( u != x );
    	}
    }
    
    bool judge( vector < int > & a ){
    	for(int i = 0 ; i < a.size() ; ++ i)
    		for(int j = i + 1 ; j < a.size() ; ++ j)
    			if( mat[a[i]][a[j]] == 0 ) 
    				return false;
    	return true;
    }
    
    int solve( int base ){
    	block.clear();
    	dfs( base );
    	if( block.size() == 4 ){
    		vector < int > dp;
    		for( auto it : block ) dp.pb( sz[it] );
    		sort( dp.begin() , dp.end() );
    		if( dp[0] == 1 && dp[1] == 1 && dp[2] == 2 && dp[3] == 2 ) return true;
    		return false;
    	}
    	ti = rt = 0;
    	predfs( base , 999999999 );	int bridgenum = 0;
    	for(auto it : block){
    		for(int i = head[it] ; ~i ; i = e[i].nxt) if( e[i].isbrige ) ++ bridgenum;
    	}
    	bridgenum >>= 1;
    	if( bridgenum == 0 || bridgenum > 3 ) return 0;
    	if( (int)block.size() & 1 ) return 0;
    	for(int i = 1 ; i <= rt ; ++ i) dcc[i].clear();
    	for(auto it : block) dcc[label[it]].pb( it );
    	if( bridgenum == 1 ){
    		if( dcc[1].size() != dcc[2].size() ) return 0 ;
    		if( !judge(dcc[1]) || !judge( dcc[2] )) return 0;
    	}else if( bridgenum == 2 ){
    		return 0;
    	}else if( bridgenum == 3 ){
    		if( block.size() != 4 ) return 0;
    	}
        return 1;
    }
    
    
    void link( int u , int v ){
    	e[tot].isbrige=0,e[tot].v=v,e[tot].nxt=head[u],head[u]=tot++;
    }
    
    int main(int argc,char *argv[]){
    	int T=read(),cas=0;
    	while(T--){
    		N=read(),M=read();
    		rep(i,1,N) rep(j,1,N) mat[i][j]=0;
    		clr(head,-1);
    		clr(sz,0);
    		clr(label,0);
    		clr(dfn,0);
    		clr( vis , 0 );
    		tot = 0;
    		rep(i,1,M){
    			int u , v ;
    			sf("%d%d",&u,&v);
    			mat[u][v] = mat[v][u] = 1;
    			sz[u] ++ ;
    			sz[v] ++ ;
    			link( u , v );
    			link( v , u );
    		}
    		int ans = 0;
    		rep(i,1,N) if(!vis[i]) ans += solve( i );
    		pf("Case #%d: %d
    ", ++ cas , ans );
    	}
    	return 0;
    }
  • 相关阅读:
    高并发的一些处理意见
    TP5单元测试
    你真的会玩SQL吗?和平大使 内连接、外连接
    微信公众号第三方平台开发概况
    MVC的基类
    Android TextView中显示图片
    Android之assets资源
    通用分页存储过程
    到处都是坑的微信支付V3之 微信支付回调页面
    微信公众平台无高级接口账号获取用户基本信息
  • 原文地址:https://www.cnblogs.com/qscqesze/p/5734038.html
Copyright © 2020-2023  润新知