zoukankan      html  css  js  c++  java
  • POJ 2186

    Tarjan之前做一道leetcode的时候刷过,这次在OJ上找找感觉。

    将整个图所有的强连通分量理出来,将整个图的强连通分量看成一个点,然后观察出度为0(这是一个DAG上的问题),分类讨论即可解决。

    其实感觉这道题利用Kosaraju也就是算法导论上关于DFS应用于求解强连通分量的方法更合适一些。

    #include <iostream>
    #include <algorithm>
    #include <queue>
    #include <string>
    #include <vector>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <string>
    #include <stack>
    #include <map>
    #include <set>
    #include <deque>
    using namespace std;
    
    const int maxn= 1e4+5;
    const int maxm= 5e4+5;
    
    vector<int> G[maxn];
    int belong[maxn], num[maxn];
    bool ins[maxn];
    int dfn[maxn], low[maxn], dg[maxn];
    int scc, tm, top;
    int S[maxn];
    
    void Tarjan(int u)
    {
    	low[u]= dfn[u]= ++tm;
    	S[++top]= u;
    	ins[u]= 1;
    	int n_eg= G[u].size();
    	for (int i= 0; i< n_eg; ++i){
    		int v= G[u][i];
    		if (!dfn[v]){
    			Tarjan(v);
    			if (low[v]< low[u]){
    				low[u]= low[v];
    			}
    		}
    		else if (ins[v] && dfn[v] < low[u]){
    			low[u]= dfn[v];
    		}
    	}
    	if (dfn[u]== low[u]){
    		int v;
    		dg[scc]= num[scc]= 0;
    		do{
    			v= S[top--];
    			ins[v]= 0;
    			belong[v]= scc;
    			++num[scc];
    		}while(v!= u);
    		++scc;
    	}
    }
    int solve(const int n)
    {
    	for (int i= 1; i<= n; ++i){
    		dfn[i]= 0;
    		ins[i]= 0;
    	}
    	tm= scc= 0;
    	top= -1;
    	for (int i= 1; i<= n; ++i){
    		if (!dfn[i]){
    			Tarjan(i);
    		}
    	}
    
    	for (int i= 1; i<= n; ++i){
    		int n_eg= G[i].size();
    		for (int j= 0; j< n_eg; ++j){
    			int v= G[i][j];
    			if (belong[i]!= belong[v]){
    				++dg[belong[i]];
    			}
    		}
    	}
    
    	int ck= 1, ans= 0;
    	for (int i= 0; i< scc; ++i){
    		if (!dg[i]){
    			--ck;
    			ans= num[i];
    		}
    	}
    
    	if (ck< 0){
    		ans= 0;
    	}
    	else if (ck){
    		ans= n;
    	}
    
    	return ans;
    }
    
    int main(int argc, char const *argv[])
    {
    	int n, m;
    	int f, t;
    	scanf("%d %d", &n, &m);
    
    	for (int i= 0; i< m; ++i){
    		scanf("%d %d", &f, &t);
    		G[f].push_back(t);
    	}
    
    	printf("%d
    ", solve(n));
    	return 0;
    }
    
  • 相关阅读:
    PAT(B) 1037 在霍格沃茨找零钱(Java)
    PAT(B) 1043 输出PATest(Java)统计
    PAT(B) 1063 计算谱半径(Java)
    绘制虚线
    contentMode
    数字签名是什么
    动态设置 button的 name 的话 闪动的问题 解决
    setValuesForKeysWithDictionary 的用法
    获得 当前时间
    iOS 键盘类型
  • 原文地址:https://www.cnblogs.com/Idi0t-N3/p/14727547.html
Copyright © 2011-2022 走看看