码迷,mamicode.com
首页 > 其他好文 > 详细

POJ - 2186 - Popular Cows (tarjan)

时间:2015-08-05 01:06:28      阅读:97      评论:0      收藏:0      [点我收藏+]

标签:poj   算法   tarjan   

题目传送:Popular Cows

思路:tarjan算法求强连通分量

AC代码:

#include <map>
#include <set>
#include <cmath>
#include <deque>
#include <queue>
#include <stack>
#include <cstdio>
#include <cctype>
#include <string>
#include <vector>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define INF 0x7fffffff
using namespace std;

const int maxn = 10005;
int n, m;

vector<int> mp[maxn];
int dfn[maxn];
int low[maxn];

int vis[maxn];
int in_stack[maxn];
int index;

int color[maxn];
int col;

bool color_is_ok[maxn];

stack<int> s;

int sum;

void tarjan(int u) {//tarjan求强连通分量 
    dfn[u] = low[u] = ++ index;
    s.push(u);
    in_stack[u] = 1;
    vis[u] = 1;
    sum ++;

    int d = mp[u].size();
    for(int i = 0; i < d; i ++) {
        int v = mp[u][i];
        if(!vis[v]) {
            tarjan(v);
            low[u] = min(low[u], low[v]);
        }
        else if(in_stack[v]) {
            low[u] = min(low[u], dfn[v]);
        }
    }

    if(dfn[u] == low[u]) {//每求到一个强连通分量然后将这个强连通分量染色 
        int v;
        do {
            v = s.top();
            s.pop();
            in_stack[v] = 0;
            color[v] = col;
        } while(u != v);
        col ++;//为了区分每个强连通分量 
    }
}

int main() {
    while(scanf("%d %d", &n, &m) != EOF) {
        for(int i = 0; i <= n; i ++) {
            mp[i].clear();
        }

        int u, v;
        for(int i = 0; i < m; i ++) {
            scanf("%d %d", &u, &v);
            mp[u].push_back(v);
        }

        memset(vis, 0, sizeof(vis));
        memset(in_stack, 0, sizeof(in_stack));
        memset(color, 0, sizeof(color));
        index = 0;
        col = 1;
        sum = 0;
        for(int i = 1; i <= n; i ++) {
            if(!vis[i]) tarjan(i);
        }

//      cout << sum << endl; 
        if(sum != n) {
            printf("0\n");
            continue;
        }

//      for(int i = 1; i <= n; i ++) cout << color[i] << " ";
//      cout << endl; 

        //标记有多少个缩点后出度为0的强连通分量 
        memset(color_is_ok, true, sizeof(color_is_ok));
        for(int i = 1; i <= n; i ++) {
            int d = mp[i].size();
            for(int j = 0; j < d; j ++) {
                if(color[mp[i][j]] != color[i]) {
                    color_is_ok[color[i]] = false;
                    break;
                }
            }
        }

//      for(int i = 1; i < col; i ++) {
//          cout << color_is_ok[i] << " ";
//      }
//      cout << endl;

        int ans_col;
        int cnt = 0;
        for(int i = 1; i < col; i ++) {
            if(color_is_ok[i]) {
                ans_col = i;
                cnt ++;
            }
        }

        if(cnt == 1) {//当且仅当只有一个强连通分量构成的缩点出度为0时有答案 
            int ans = 0;
            for(int i = 1; i <= n; i ++) {
                if(color[i] == ans_col) {
                    ans ++;
                }
            }
            printf("%d\n", ans);
        }
        else {
            printf("0\n");
        }
    }
    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

POJ - 2186 - Popular Cows (tarjan)

标签:poj   算法   tarjan   

原文地址:http://blog.csdn.net/u014355480/article/details/47285537

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!