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

杭电1269--迷宫城堡(强连通分量)

时间:2015-09-11 23:31:18      阅读:247      评论:0      收藏:0      [点我收藏+]

标签:

题目:http://acm.hdu.edu.cn/showproblem.php?pid=1269

 

 

连通分量, 断断续续看了几天, 今天终于A了道强联通分量SCC)模板题。 初学SCC, 理解的还不是很好, 是利用Dfs中回溯过程进行操作, 细节掌握还不够好。 

 

本题题意是判断有向图中SCC 个数是否唯一, 模板题; 

#include <stack>
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;

const int N = 10001;

struct Edge
{
    int from, to, next;
} edge[100100];

int n, m, cnt, cnt_SCC, vis_num, low[N], tim[N], head[N], instack[N];
void Add(int a, int b)
{
    Edge E = {a, b, head[a]};
    edge[cnt] = E;
    head[a] = cnt++;    
}

stack <int>S;
void TarJan(int x)
{
    int j;
    tim[x] = low[x] = ++vis_num;
    instack[x] = 1;
    S.push(x);
    for(int i = head[x]; i != -1; i = edge[i].next)
    {
        int u = edge[i].to;
        if(tim[u] == -1)
        {
            TarJan(u);
            if(low[x] > low[u])
                low[x] = low[u];
        }
        else if(instack[u] && low[x] > tim[u])
            low[x] = tim[u];
    }
    if(low[x] == tim[x])
    {
        cnt_SCC++;
        do{
            j = S.top();
            S.pop();
            instack[j] = 0
        } while(j != x);
    }     
}

void Solve()
{
    vis_num = cnt_SCC = 0
    for(int i = 1; i <= n; i++)
        if(tim[i] == -1)
            TarJan(i);
    if(cnt_SCC == 1)
        puts("Yes");
    else
        puts("No");
}

void GetMap()
{
    int a, b;
    memset(instack, 0sizeof(instack));
    memset(low, 0sizeof(low));
    memset(tim, -1sizeof(tim));
    
    cnt = 0;
    memset(head, -1sizeof(head));
    while(m--)
    {
        scanf("%d%d", &a, &b);
        Add(a, b);
    }
}

int main()
{
    while(~scanf("%d%d", &n, &m), n+m)
    {
        GetMap();
        Solve();
    }
    return 0;   
技术分享MyGod
1 大神解析(SCC_TarJan):
2 http://blog.sina.com.cn/s/blog_7a1746820100vtk9.html
3 http://www.cnblogs.com/saltless/archive/2010/11/08/1871430.html

 

贴个并查集做法, 并查集有点好用。 两个并查集,一个反向处理有向边。  

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
int father[3][10001];

int find(int a, int i)
{
    if(father[i][a] == a)
        return a;
    else
        return find(father[i][a], i);
}

int n, m;
void mercy(int a , int b)
{
    int P, Q; 
    if(a != n)                //Important; 
    {
        P = find(a, 0);
        Q = find(b, 0);
        if(P != Q)
            father[0][a] = b;  // Detail;
    }    
    if(b != n)
    {
        P = find(a, 1);
        Q = find(b, 1);
        if(P != Q)
            father[1][b] = a;  
    }
}

int main()
{
    while(~scanf("%d%d", &n, &m), n+m)
    {
        for(int i = 1; i <= n; i++)
            father[0][i] = father[1][i] = i;
        for(int i = 1; i <= m; i++)
        {
            int a, b;
            scanf("%d%d", &a, &b);
            mercy(a, b);    
        }
        bool flag = true;
        for(int i = 1; i <= n; i++)
        {
            if(find(i, 0) != n || find(i, 1) != n)    
            {
                flag = false;
                break
            }
        }
        if(flag)
            printf("Yes\n"); 
        else
            printf("No\n");
    } 
    return 0;
} 

杭电1269--迷宫城堡(强连通分量)

标签:

原文地址:http://www.cnblogs.com/fengshun/p/4802313.html

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