• POJ1904(King's Quest)


    题目链接

    此题初看起来是一个二分匹配的问题,一个国王有n个儿子,将要与n个女孩结婚,已知每个儿子喜欢某几个女孩,并给出了一个初始匹配,问题是求每个儿子可能与哪些他喜欢的女孩结婚,一旦他选一个结婚后,其他的儿子仍能选到自己喜欢的人结婚。若直接枚举个中可能,然后用匈牙利算法求完美匹配判断,这样的话时间复杂度是O(n5),毫无疑问会超时。在这里,题目给出里一个初始完美匹配,必须加以利用。我们可以把初始完美匹配中的每一对看成结点进行构图,因此每个结点包含一个男孩和一个女孩,若结点i中的男孩喜欢结点j中的女孩,就在结点i与结点j之间连一条有向边,这样问题就转化为求强分图,每个男孩可以与他喜欢的并且与他在同一个强分图中的一个女孩结婚且不影响到其他人。求强分图,我用的是两次dfs的算法。

    View Code
     1 #include <stdio.h>
    2 #include <string.h>
    3 #define CLR(a) (memset(a,0,sizeof(a)))
    4 #define N 2005
    5 char vis[N],g[N][N];
    6 int boy[N],girl[N],n;
    7 int ord[N],id[N],cnt;
    8 void dfs(int u)
    9 {
    10 int i,v;
    11 vis[u]=1;
    12 for(i=0;i<n;i++)
    13 {
    14 if(g[u][i])
    15 {
    16 v=boy[i];
    17 if(!vis[v]) dfs(v);
    18 }
    19 }
    20 ord[cnt++]=u;
    21 }
    22 void rdfs(int u)
    23 {
    24 int i=girl[u],v;
    25 vis[u]=1,id[u]=cnt;
    26 for(v=0;v<n;v++)
    27 {
    28 if(g[v][i]&&!vis[v]) rdfs(v);
    29 }
    30 }
    31 void kosaraju()
    32 {
    33 int i,j,v,t,ans[N],num;
    34 CLR(vis);
    35 for(i=0,cnt=0;i<n;i++)
    36 {
    37 if(!vis[i]) dfs(i);
    38 }
    39 CLR(vis);
    40 for(t=n-1,cnt=0;t>=0;t--)
    41 {
    42 i=ord[t];
    43 if(!vis[i])
    44 {
    45 rdfs(i);
    46 cnt++;
    47 }
    48 }
    49 for(i=0;i<n;i++)
    50 {
    51 for(v=0,num=0;v<n;v++)
    52 {
    53 if(!g[i][v]) continue;
    54 j=boy[v];
    55 if(id[i]==id[j]) ans[num++]=v+1;
    56 }
    57 printf("%d",num);
    58 for(j=0;j<num;j++) printf(" %d",ans[j]);
    59 printf("\n");
    60 }
    61 }
    62 int main()
    63 {
    64 int i,j,k;
    65 while(scanf("%d",&n)!=EOF)
    66 {
    67 CLR(g);
    68 for(i=0;i<n;i++)
    69 {
    70 scanf("%d",&k);
    71 while(k--)
    72 {
    73 scanf("%d",&j);
    74 g[i][j-1]=1;
    75 }
    76 }
    77 for(i=0;i<n;i++)
    78 {
    79 scanf("%d",&j);
    80 girl[i]=j-1;
    81 boy[girl[i]]=i;
    82 }
    83 kosaraju();
    84 }
    85 return 0;
    86 }
  • 相关阅读:
    剑指 Offer 06. 从尾到头打印链表
    剑指 Offer 05. 替换空格
    剑指 Offer 04. 二维数组中的查找
    14. 不修改数组找出重复的数字
    剑指 Offer 03. 数组中重复的数字
    231. 2 的幂
    1394. 完美牛棚
    10. 正则表达式匹配
    3726. 调整数组
    474. 一和零
  • 原文地址:https://www.cnblogs.com/algorithms/p/2432475.html
Copyright © 2020-2023  润新知