zoukankan      html  css  js  c++  java
  • UVa 1364

    题目链接:https://onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&category=0&problem=4110&mosmsg=Submission+received+with+ID+26571544

    如果两个骑士不互相讨厌,即可以相邻,则参加会议的骑士在无向图中组成简单奇圈。简单圈上的所有结点必定属于同一个双连通分量,所以要先找出所有的双连通分量。而二分图是没有奇圈的,所以找出不是二分图的双连通分量,对双连通分量二分图染色判断即可。可以证明,存在奇圈的双连通分量中的所有节点都在奇圈上。给这些双连通分量中的点打上标记统计答案即可。

    时间复杂度 (O(n))

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    const int maxn = 1010; 
    const int maxm = 1000010;
    
    int n, m;
    int g[maxn][maxn];
    
    int h[maxn], cnt = 0;
    struct E{
    	int from, to, next;
    }e[maxm << 1];
    void add(int u, int v){
    	e[++cnt].to = v;
    	e[cnt].from = u;
    	e[cnt].next = h[u];
    	h[u] = cnt;
    }
    
    stack<E> s;
    vector<int> bcc[maxn];
    
    int st[maxn], iscut[maxn], bccno[maxn], low[maxn], dfn = 0, bcc_cnt = 0;
    
    int dfs(int u, int par){
    	int lowu = st[u] = ++dfn;
    	int child = 0;
    	for(int i = h[u] ; i != -1 ; i = e[i].next){
    		int v = e[i].to;
    		E e = (E){u, v, -1};
    		if(!st[v]){
    			s.push(e);
    			++child;
    			int lowv = dfs(v, u); 
    			lowu = min(lowu, lowv);
    			if(lowv >= st[u]){
    				iscut[u] = 1;
    				bcc_cnt++; 
    				bcc[bcc_cnt].clear();
    				for(;;){
    					E x = s.top(); s.pop();
    					if(bccno[x.from] != bcc_cnt){ bcc[bcc_cnt].push_back(x.from); bccno[x.from] = bcc_cnt; }
    					if(bccno[x.to] != bcc_cnt){ bcc[bcc_cnt].push_back(x.to); bccno[x.to] = bcc_cnt; }
    					if(x.from == u && x.to == v) break;
    				}
    			}
    		} else if(st[v] < st[u] && v != par){ // 反向边更新 
    			s.push(e);
    			lowu = min(lowu, st[v]);
    		}
    	}
    	if(par == 0 && child == 1) iscut[u] = 0;
    	low[u] = lowu;
    	return low[u];
    }
    
    void tarjan(){
    	memset(st, 0, sizeof(st));
    	memset(iscut, 0, sizeof(iscut));
    	memset(bccno, 0, sizeof(bccno));
    	dfn = bcc_cnt = 0;
    	 
    	for(int i = 1 ; i <= n ; ++i){
    		if(!st[i]) dfs(i, 0);
    	}
    }
    
    int odd[maxn], color[maxn];
    
    bool bipartite(int u, int b){
    	for(int i = h[u] ; i != -1 ; i = e[i].next){
    		int v = e[i].to;
    		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;
    } 
    
    ll read(){ ll s = 0, f = 1; char ch = getchar(); while(ch < '0' || ch > '9'){ if(ch == '-') f = -1; ch = getchar(); } while(ch >= '0' && ch <= '9'){ s = s * 10 + ch - '0'; ch = getchar(); } return s * f; }
    
    int main(){
    	while(scanf("%d%d", &n, &m) == 2 && n){
    		memset(h, -1, sizeof(h)); cnt = 0; dfn = 0;
    		memset(g, 0, sizeof(g));
    		
    		int u, v;
    		for(int i = 1 ; i <= m ; ++i){
    			scanf("%d%d", &u, &v);
    			g[u][v] = g[v][u] = 1;
    		}
    		
    		for(int i = 1 ; i <= n ; ++i){
    			for(int j = i + 1 ; j <= n ; ++j){
    				if(!g[i][j]) {
    					add(i, j); add(j, i);
    				}
    			}
    		}
    		
    		tarjan();
    		
    		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 = 1 ; i <= n ; ++i) if(odd[i]) --ans;
    		printf("%d
    ", ans); 
    	}
    	return 0;
    }
    
  • 相关阅读:
    开始我的博客园
    科技生态链
    程式建议
    如何自动识别判断url中的中文参数是GB2312还是Utf-8编码?
    jquery.cookie 使用方法
    数据结构(Java)——查找和排序(5)
    数据结构(Java)——查找和排序(4)
    数据结构(Java)——查找和排序(3)
    数据结构(Java)——查找和排序(2)
    数据结构(Java)——查找和排序(1)
  • 原文地址:https://www.cnblogs.com/tuchen/p/15013328.html
Copyright © 2011-2022 走看看