zoukankan      html  css  js  c++  java
  • poj 2942 Knights of the Round Table 双连通分量

    白书上的代码

    #include<cstdio>
    #include<stack>
    #include<vector>
    #include<algorithm>
    #include<cstring>
    
    using namespace std;
    
    struct Edge { int u, v; };
    
    const int maxn = 1000 + 10;
    int pre[maxn], iscut[maxn], bccno[maxn], dfs_clock, bcc_cnt; // 割顶的bccno无意义
    vector<int> G[maxn], bcc[maxn];
    
    stack<Edge> S;
    
    int dfs(int u, int fa) 
    {
    	int lowu = pre[u] = ++dfs_clock;
    	int child = 0;
    	for(int i = 0; i < G[u].size(); i++) 
    	{
    		int v = G[u][i];
    		Edge e;
    		e.u=u;
    		e.v=v;
    		if(!pre[v]) 
    		{ // 没有访问过v
    			S.push(e);
    			child++;
    			int lowv = dfs(v, u);
    			lowu = min(lowu, lowv); // 用后代的low函数更新自己
    			if(lowv >= pre[u]) 
    			{
    				iscut[u] = true;
    				bcc_cnt++; bcc[bcc_cnt].clear();
    				for(;;) 
    				{
    					Edge x = S.top(); S.pop();
    					if(bccno[x.u] != bcc_cnt) { bcc[bcc_cnt].push_back(x.u); bccno[x.u] = bcc_cnt; }
    					if(bccno[x.v] != bcc_cnt) { bcc[bcc_cnt].push_back(x.v); bccno[x.v] = bcc_cnt; }
    					if(x.u == u && x.v == v) break;
    				}
    			}
    		}
    		else if(pre[v] < pre[u] && v != fa) {
    		S.push(e);
    		lowu = min(lowu, pre[v]); // 用反向边更新自己
    		}
    	}
    	if(fa < 0 && child == 1) iscut[u] = 0;
    	return lowu;
    }
    
    void find_bcc(int n) 
    {
    	// 调用结束后S保证为空,所以不用清空
    	memset(pre, 0, sizeof(pre));
    	memset(iscut, 0, sizeof(iscut));
    	memset(bccno, 0, sizeof(bccno));
    	dfs_clock = bcc_cnt = 0;
    	for(int i = 0; i < n; i++)
        if(!pre[i]) dfs(i, -1); 
    }
    
    int odd[maxn], color[maxn];
    bool bipartite(int u, int b) 
    {
    	for(int i = 0; i < G[u].size(); i++) 
    	{
    		int v = G[u][i]; if(bccno[v] != b) continue;
    		if(color[v] == color[u]) return false;
    		if(!color[v]) 
    		{
    			color[v] = 3 - color[u];
    			if(!bipartite(v, b)) return false;
    		}
    	}
    	return true;
    }
    
    int A[maxn][maxn];
    
    int main() 
    {
    	int kase = 0, n, m;
    	while(scanf("%d%d", &n, &m) == 2 && n) 
    	{
    		for(int i = 0; i < n; i++) G[i].clear();
    		memset(A, 0, sizeof(A));
    		for(int i = 0; i < m; i++) 
    		{
    			int u, v;
    			scanf("%d%d", &u, &v); u--; v--; A[u][v] = A[v][u] = 1;
    		}
    		for(int u = 0; u < n; u++)
    			for(int v = u+1; v < n; v++)
    				if(!A[u][v]) { G[u].push_back(v); G[v].push_back(u); }
    
    		find_bcc(n);
    
    		memset(odd, 0, sizeof(odd));
    		for(int i = 1; i <= bcc_cnt; i++) 
    		{
    			memset(color, 0, sizeof(color));
    			for(int j = 0; j < bcc[i].size(); j++) bccno[bcc[i][j]] = i; // 主要是处理割顶
    			int u = bcc[i][0];
    			color[u] = 1;
    			if(!bipartite(u, i))
    			for(int j = 0; j < bcc[i].size(); j++) odd[bcc[i][j]] = 1;
    		}
    		int ans = n;
    		for(int i = 0; i < n; i++) if(odd[i]) ans--;
    		printf("%d
    ", ans);
    	}
    	return 0;
    }
    


     

  • 相关阅读:
    python 返回函数的使用
    你的服务器还在裸奔吗?
    云计算产品vSwitch原理
    网卡创建Bond
    UI自动化框架介绍
    常用底层linux命令
    Linux Bridge基本概念
    磁盘格式化及设置自动挂载
    Linux vi文本编辑器常用命令
    MySQL5.7安装方式
  • 原文地址:https://www.cnblogs.com/vermouth/p/3710174.html
Copyright © 2011-2022 走看看