poj-1904

来源:互联网 发布:网络教育英语b统考 编辑:程序博客网 时间:2024/05/18 02:49

题目来源: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 }

 

原创粉丝点击