King's Quest POJ - 1904(强连通分量)

建图:王子u喜欢女孩v,则u到v连一条边。对于给出的初始完美匹配,王子u与女孩v匹配,则v到u连一条边。然后求SCC。

显然对于同一个SCC中王子数目和女孩数目是相等的,并且从某个王子出发能够到达所有女孩,这样,王子可以和属于同一个SCC中的任意一个女孩结婚,而不会影响其他王子。

 

 

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#define mem(a, b) memset(a, b, sizeof(a))
using namespace std;
const int maxn = 500100, INF = 0x7fffffff;
int pre[maxn], low[maxn], sccno[maxn], dfs_clock, scc_cnt, cnt;
int head[maxn];
vector<int> G[maxn];
stack<int> S;
int n, k;
struct node
{
    int u, v, next;
}Node[maxn];

void add(int u, int v)
{
    Node[cnt].u = u;
    Node[cnt].v = v;
    Node[cnt].next = head[u];
    head[u] = cnt++;
}


void dfs(int u)
{
    pre[u] = low[u] = ++dfs_clock;
    S.push(u);
    for(int i=head[u]; i!=-1; i=Node[i].next)
    {
        int v = Node[i].v;
        if(!pre[v])
        {
            dfs(v);
            low[u] = min(low[u], low[v]);
        }
        else if(!sccno[v])
            low[u] = min(low[u], pre[v]);
    }
    if(low[u] == pre[u])
    {
        scc_cnt++;
        for(;;)
        {
            int x = S.top(); S.pop();
            sccno[x] = scc_cnt;
            if(x == u) break;
        }
    }
}

void init()
{
    cnt = 0;
    mem(head, -1);
    mem(pre, 0);
    mem(low, 0);
    mem(sccno, 0);
}


int main()
{
    init();
    scanf("%d",&n);
    for(int i=1; i<=n; i++)
    {
        scanf("%d",&k);
        for(int j=0; j<k; j++)
        {
            int v;
            scanf("%d",&v);
            add(i, n+v);
        }
    }
    for(int i=1; i<=n; i++)
    {
        int v;
        scanf("%d",&v);
        add(n+v, i);
    }
    for(int i=1; i<=n; i++)
        if(!pre[i])
            dfs(i);
  //  cout<< 1211 <<endl;
    for(int i=1; i<=n; i++)
    {
        for(int j=head[i]; j!=-1; j=Node[j].next)
        {
            if(sccno[i] == sccno[Node[j].v])
            {
                G[i].push_back(Node[j].v);
            }
        }
    }
    for(int i=1; i<=n; i++)
        sort(G[i].begin(), G[i].end());
    for(int i=1; i<=n; i++)
    {
        printf("%d ",G[i].size());
        for(int j=0; j<G[i].size(); j++)
            printf("%d%s",G[i][j] - n,(j==G[i].size()-1)?"\n":" ");
    }



    return 0;
}
View Code

 

posted @ 2018-07-13 23:31  WTSRUVF  阅读(173)  评论(0编辑  收藏  举报