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 }
- poj 1904
- poj 1904
- poj-1904
- POJ 1904 强连通
- poj 1904 强连通
- POJ 1904 HDU 4685
- poj 1904 Tarjan
- POJ 1904 思路题
- POJ
- poj
- POJ
- POJ
- poj
- poj
- POJ
- POJ
- poj
- POJ
- 还是畅通工程 hdu1233 Prim
- 中兴N880e升级android4.2版本体验
- 使用反射给vo赋值
- CSS文档流与块级元素和内联元素
- 在mac上编译openssl
- poj-1904
- poj-1236
- USACO-Barn Repair
- USACO-Milking Cows
- USACO-Calf Flac
- USACO-Prime Cryptarithm
- USACO-Packing Rectangles
- USACO-Arithmetic Progressions
- USACO-Mother's Milk