poj-1904

题目来源:http://poj.org/problem?id=1904

大意:N个王子和N个美女配对,每个王子喜欢一个或多个美女,大臣已经配好了一个列表,但是国王想知道每个王子和美女的可行匹配。就是求出每个王子可以选择哪些美女

思路:对于每对男女u,v,连边(u,u+n),而输入的最后给出一个可行匹配,则对于每个美女v和配对的王子u,连边(v+n,u),然后求出图的强联通分量,最后计数输出就是了。

这是用vector储存的程序,5000ms+

View Code
 1 #include <stdio.h>
 2 #include <string>
 3 #include <vector>
 4 #include <algorithm>
 5 using namespace std;
 6 
 7 #define NN 5005
 8 vector <int> a[NN];
 9 vector <int> b[NN];
10 int real[NN],low[NN],p[NN],color[NN];
11 bool f[NN];
12 int n,top,total,timee;
13 
14 void tarjan(int h)
15 {
16      p[++top]=h;
17      f[h]=true;
18      real[h]=low[h]=++timee;
19      for (int i=0;i<a[h].size();i++)
20      {
21          if (!real[a[h][i]])
22          {
23                          tarjan(a[h][i]);
24                          low[h]=min(low[h],low[a[h][i]]);
25          }
26          else if (f[a[h][i]]) low[h]=min(low[h],real[a[h][i]]);
27      }
28      
29      if (real[h]==low[h])
30      {
31                          total++;
32                          while (p[top+1]!=h)
33                          {
34                                color[p[top]]=total;
35                                f[p[top]]=false;
36                                top--;
37                          }
38      }
39 }
40 
41 int main()
42 {
43     scanf("%d",&n);
44     int m,x;
45     for (int i=1;i<=n;i++)
46     {
47         scanf("%d",&m);
48         for (int j=0;j<m;j++)
49         {
50             scanf("%d",&x);
51             a[i].push_back(x+n);
52         }
53     }
54     for (int i=1;i<=n;i++)
55     {
56         scanf("%d",&x);
57         a[x+n].push_back(i);
58     }
59     
60     memset(real,0,sizeof(real));
61     memset(low,0,sizeof(low));
62     memset(p,0,sizeof(p));
63     memset(f,false,sizeof(f));
64     top=total=timee=0;
65     for (int i=1;i<=n;i++)
66         if (!real[i]) 
67            tarjan(i);
68     
69     for (int i=1;i<=n;i++)
70         b[i].clear();
71     for (int i=1;i<=n;i++)
72     {
73         for (int j=0;j<a[i].size();j++)
74             if (color[i]==color[a[i][j]])
75             b[i].push_back(a[i][j]-n);
76         sort(b[i].begin(),b[i].end());
77     }
78     for (int i=1;i<=n;i++)
79     {
80         printf("%d",b[i].size());
81         for (int j=0;j<b[i].size();j++)
82             printf(" %d",b[i][j]);
83         printf("\n");
84     }
85     return 0;
86 }

这是用池子法(前向星法)写的程序,3000ms+

View Code
  1 #include <stdio.h>
  2 #include <cstring>
  3 #include <algorithm>
  4 using namespace std;
  5 
  6 #define maxn 20005
  7 #define maxm 2000005
  8 struct node {
  9        int y,next;
 10 }p[maxm];
 11 
 12 int head[maxn],a[maxm];
 13 int n,m,cl;
 14 bool instack[maxn];
 15 int real[maxn],low[maxn],stack[maxn],color[maxn];
 16 int depth,top,total;
 17 
 18 void add(int x,int y)
 19 {
 20      p[++cl].y=y;
 21      p[cl].next=head[x];
 22      head[x]=cl;
 23 }
 24 
 25 void dfs(int x)
 26 {
 27      int y;
 28      real[x]=low[x]=++depth;
 29      instack[x]=true;
 30      stack[++top]=x;
 31      for (int i=head[x];i!=-1;i=p[i].next)
 32      {
 33          y=p[i].y;
 34          if (!real[y])
 35          {
 36                       dfs(y);
 37                       low[x]=min(low[x],low[y]);
 38          }
 39          else if (instack[y])
 40               low[x]=min(low[x],real[y]);
 41      }
 42      
 43      if (real[x]==low[x])
 44      {
 45                          total++;
 46                          while (stack[top+1]!=x)
 47                          {
 48                                y=stack[top--];
 49                                instack[y]=false;
 50                                color[y]=total;
 51                          }
 52      }
 53 }
 54      
 55 
 56 void tarjan()
 57 {
 58      memset(real,0,sizeof(real));
 59      memset(low,0,sizeof(low));
 60      memset(instack,false,sizeof(instack));
 61      depth=top=total=0;
 62      for (int i=1;i<=n*2;i++)
 63          if (!real[i])
 64             dfs(i);
 65 }
 66 
 67 void solve()
 68 {
 69      int y;
 70      for (int i=1;i<=n;i++)
 71      {
 72          top=0;
 73          for (int j=head[i];j!=-1;j=p[j].next)
 74          {
 75              y=p[j].y;
 76              if (color[y]==color[i])
 77                 a[top++]=y-n;
 78          }
 79          printf("%d",top);
 80          sort(a,a+top);
 81          for (int j=0;j<top;j++)
 82              printf(" %d",a[j]);
 83          printf("\n");
 84      }
 85 }
 86 
 87 int main()
 88 {
 89     scanf("%d",&n);
 90     int x,y;
 91     memset(head,-1,sizeof(head));
 92     cl=0;
 93     for (int i=1;i<=n;i++)
 94     {
 95         scanf("%d",&y);
 96         while (y--)
 97         {
 98               scanf("%d",&x);
 99               add(i,x+n);
100         }
101     }
102     for (int i=1;i<=n;i++)
103     {
104         scanf("%d",&x);
105         add(x+n,i);
106     }
107     tarjan();
108     solve();
109     return 0;
110 }

 

posted @ 2012-08-22 20:17  ay27  阅读(104)  评论(0编辑  收藏  举报