POJ 1904 【强连通分量】.cpp

题意:

  很久很久以前..

  有一个国王..

  他有好几个儿子..

  这些王子都喜欢上了邻国的公主..

  他们准备迎娶自己喜欢的公主中的一个..

  国王就让宰相给列一个清单..

  

  宰相就给了国王一个清单..上面写明了哪个王子将迎娶哪个邻国的公主..

  但是调皮的国王不太满意~~

  他还想知道他的儿子分别可以迎娶哪几个公主中的一个而不会让他的兄弟因此而吃醋..

  所以宰相又得重新写清单了..

 

  噢..对了~邻国的公主和王子人数一样多~<这是一个奇怪的国家..>

  输入:

  一个n表示有n个王子..

  接下来n行每行有一个m表示第i个王子喜欢m个公主..

  然后给出m个公主的序号..

  最后一行有n个数..代表第i个王子最后迎娶了的公主..

 

  输出:

  n行..每行第一个是m 表示有m个公主他可以选择~

  然后m个数是公主的序号..

  P.S 麻烦的国王还要求公主序号按从小到大给出..

<这是一些花心的王子..= =!! 可恨..>

 

思路:

  求强连通分量..

  王子和喜欢的公主连边..

  最后娶了的公主和该王子之间也连边..

  然后每个强连通分量就是他可以选择的公主序号..

 

Tips:

  因为类似拆点了..所以数组要开大一点..

 

Code:

View Code
  1 #include <stdio.h>
  2 #include <cstring>
  3 #include <algorithm>
  4 using namespace std;
  5 const int INF = 0x1f1f1f1f;
  6 #define clr(x) memset(x, 0, sizeof(x))
  7 const int MAXN = 2010*3;
  8 
  9 struct Edge
 10 {
 11     int to;
 12     int next;
 13 }edge[10000010];
 14 int head[MAXN];
 15 int tot;
 16 
 17 void add(int s, int u)
 18 {
 19     edge[tot].to = u;
 20     edge[tot].next = head[s];
 21     head[s] = tot++;
 22 }
 23 
 24 int dfn[MAXN], low[MAXN];
 25 int ins[MAXN], sta[MAXN], col[MAXN];
 26 int ti, top, cnt;
 27 int n;
 28 
 29 void tarjan(int u)
 30 {
 31     int i, k;
 32     dfn[u] = low[u] = ++ti;
 33     ins[u] = 1;
 34     sta[++top] = u;
 35     for(i = head[u]; i != -1; i = edge[i].next) {
 36         k = edge[i].to;
 37         if(dfn[k] == 0) {
 38             tarjan(k);
 39             low[u] = min(low[u], low[k]);
 40         } else if(ins[k]) {
 41             low[u] = min(low[u], dfn[k]);
 42         }
 43     }
 44     if(dfn[u] == low[u]) {
 45         cnt++;
 46         do
 47         {
 48             k = sta[top--];
 49             col[k] = cnt;
 50             ins[k] = 0;
 51         }while(u != k);
 52     }
 53 
 54 }
 55 
 56 void solve()
 57 {
 58     int i, k;
 59     ti = top = cnt = 0;
 60     clr(dfn);
 61     for(i = 1; i <= n; ++i)
 62         if(!dfn[i])
 63             tarjan(i);
 64 }
 65 
 66 int main()
 67 {
 68     int i, j, k;
 69     int a, m;
 70     int mar;
 71     int ans[MAXN];
 72     while(scanf("%d", &n) != EOF)
 73     {
 74         tot = 0;
 75         memset(head, 0xff, sizeof(head));
 76 
 77         for(i = 1; i <= n; ++i) {
 78             scanf("%d", &m);
 79             while(m--) {
 80                 scanf("%d", &a);
 81                 add(i, a+n);
 82             }
 83         }
 84         for(i = 1; i <= n; ++i) {
 85             scanf("%d", &mar);
 86             add(mar+n, i);
 87         }
 88 
 89         solve();
 90 
 91         int tmp;
 92         for(i = 1; i <= n; ++i) {
 93             tmp = 0;
 94             for(j = head[i]; j != -1; j = edge[j].next) {
 95                 k = edge[j].to;
 96                 if(col[i] == col[k])
 97                     ans[tmp++] = k;
 98             }
 99             sort(ans, ans+tmp);
100             printf("%d", tmp);
101             for(j = 0; j < tmp; ++j)
102                 printf(" %d", ans[j]-n);
103             puts("");
104         }
105     }
106     return 0;
107 }

 

 

题目链接:http://poj.org/problem?id=1904

posted @ 2012-10-05 07:54  Griselda.  阅读(179)  评论(0编辑  收藏  举报