POJ 2553 —— The Bottom of a Graph

原題:http://poj.org/problem?id=2553


題意:給出n個點,m條邊的有向圖;問有多少個點 v 滿足—— v能到u,u也能到v(v能到達的所有點都要能回到v);

思路:出度 = 0 的強連通分量裏的點都滿足該情況;


#include<cstdio>  
#include<string>  
#include<cstring>  
#include<queue>
#include<vector>  
#include<algorithm>  
#define inf 0x3f3f3f3f  
using namespace std;  
const int maxn = 5005;  
  
int n, m;  
int DFN[maxn], Low[maxn], Stack[maxn], Belong[maxn];  
bool Instack[maxn];  
int Time, taj, top;  
int head[maxn], edgenum;  
  
struct Edge  
{  
    int from, to, next;  
}edge[maxn*maxn]; 

vector<int>bcc[maxn];
void tarjan(int u, int fa)
{    
    DFN[u] = Low[u] = ++Time;    
    Stack[top++] = u;    
    Instack[u] = true;   
  
    for(int i = head[u];i != -1;i = edge[i].next)
	{    
        int v = edge[i].to ;    
        if(DFN[v] == -1)  
        {    
            tarjan(v, u) ;    
            Low[u] = min(Low[u], Low[v]);   
        }    
        else if(Instack[v] && Low[u] > DFN[v]) 
			Low[u] = DFN[v];        
    }    
    if(Low[u] == DFN[u])
	{     
        taj++; 
		bcc[taj].clear();  
        while(1)
		{  
            int now = Stack[--top];    
            Instack[now] = false;   
            Belong[now] = taj;  
            bcc[taj].push_back(now);  
            if(now == u)	break;
        }
    }  
}  
  
void tarjan_init(int all)
{  
    memset(DFN, -1, sizeof DFN);  
    memset(Instack, false, sizeof Instack);  
    top = Time = taj = 0;  
    for(int i = 1;i<=all;i++)
    {
    	if(DFN[i] == -1)
		tarjan(i, i);
	}
}

void add(int u, int v)  
{  
    edge[edgenum].from = u;  
    edge[edgenum].to = v;  
    edge[edgenum].next = head[u];  
    head[u] = edgenum++;  
}

vector<int>G[maxn];
int du[maxn];
void suodian()
{
	for(int i = 1;i<=taj;i++)	G[i].clear();
	memset(du, 0, sizeof du);
	for(int i = 0;i<edgenum;i++)
	{  
        int u = Belong[edge[i].from];
		int v = Belong[edge[i].to];  
        if(u != v)
		{
			G[u].push_back(v);
			du[u]++;
		} 
    }
}

void init()
{
	memset(head, -1, sizeof head);
	edgenum = 0;
}

int main()
{
	while(~scanf("%d", &n) && n)
	{
		scanf("%d", &m);
		init();
		while(m--)
		{
			int u, v;
			scanf("%d%d", &u, &v);
			add(u, v);
		}
		tarjan_init(n);
		suodian();
		int ans[maxn];
		int cnt = 0;
		for(int i = 1;i<=taj;i++)
		{
			if(du[i] == 0)
			{
				for(int j = 0;j<(int)bcc[i].size();j++)
				{
					int x = bcc[i][j];
					ans[cnt++] = x;
				}
			}
		}
		sort(ans, ans+cnt);
		for(int i = 0;i<cnt;i++)
		{
			if(i == cnt-1)
			printf("%d\n", ans[i]);
			else
			printf("%d ", ans[i]);
		}
	}
	return 0;	
}


發佈了60 篇原創文章 · 獲贊 1 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章