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 }