• POJ 1904(强连通分量)Tarjan


    题意描述:有n个王子和n个美女,每个王子有自己喜欢的美女,保证每个王子都能娶到一个自己喜欢的美女,现在巫师给出了一个王子和美女匹配的方案,但是国王想知道每个王子能够娶到的美女的名单(保证每个王子都能娶到美女)

     

    思路:一看就是二分图,求所有可行的完全匹配的边集,但是想想二分图里面没有可以直接或者间接套用的算法。

    不知道大家看到数据提供的一组匹配时是什么感想,应该要猜测到这组数据肯定有用。

    那么假设现在我们按照数据提供的匹配已经匹配好了,这是对于u王子,如果他和v美女(非原配)匹配的话,到最后,则必然要有另一个王子和u的原配美女匹配

    想想,发现这是一个环,想到强连通了么??

    先别看以下的内容,先思考再看!

    构图:每个王子向他喜欢的美女连一条有向边,对于数据中的匹配,每个美女向其匹配的王子连一条有向边,然后强连通就行了。

    PS:注意在同一个强连通分量中的美女并不是都能和在该连通分量王子匹配(王子不一定喜欢她,为此狂WA,单恋就是不好。。。)

    View Code
     1 #include <cstdio>
     2 #include <cstdlib>
     3 #include <cstring>
     4 #include <iostream>
     5 #define N 5000
     6 #define M 700000 
     7 using namespace std;
     8 int n,t,divg,cnt,p,stack[N],head[N],to[M],next[M],dfn[N],low[N],belong[N],map[2001][2001];
     9 bool fg[N];
    10 inline void add(int u,int v) 
    11 {
    12     to[cnt]=v; next[cnt]=head[u]; head[u]=cnt++;
    13 }
    14 void read()
    15 {
    16     memset(fg,0,sizeof fg);
    17     memset(head,-1,sizeof head); cnt=0;
    18     memset(dfn,0,sizeof dfn);
    19     memset(belong,0,sizeof belong);
    20     memset(map,0,sizeof map);
    21     t=0; divg=0; p=0;
    22     for(int i=1,a,b;i<=n;i++)
    23     {
    24         scanf("%d",&a);
    25         while(a--) scanf("%d",&b),add(i,n+b),map[i][b]=true;
    26     }
    27     for(int i=1,a;i<=n;i++) scanf("%d",&a),add(a+n,i);
    28 }
    29 void dfs(int u)
    30 {
    31     t++;
    32     dfn[u]=low[u]=t;
    33     stack[++p]=u; fg[u]=true;
    34     for(int i=head[u];~i;i=next[i])
    35     {
    36         if(!dfn[to[i]])
    37         {
    38             dfs(to[i]);
    39             low[u]=min(low[u],low[to[i]]);
    40         }
    41         else if(fg[to[i]]) low[u]=min(low[u],dfn[to[i]]);
    42     }
    43     if(dfn[u]==low[u])
    44     {
    45         divg++;
    46         int tmp=-1;
    47         while(tmp!=u)
    48         {
    49             tmp=stack[p--];
    50             belong[tmp]=divg;
    51             fg[tmp]=false;
    52         }
    53     }
    54 }
    55 void go()
    56 {
    57     for(int i=1;i<=n;i++)
    58         if(!dfn[i]) dfs(i);
    59     for(int i=1,num;i<=n;i++)
    60     {
    61         num=0;
    62         for(int j=n+1;j<=n+n;j++)
    63             if(belong[j]==belong[i]&&map[i][j-n]) num++;
    64         printf("%d ",num);
    65         for(int j=n+1;j<=n+n;j++)
    66             if(belong[j]==belong[i]&&map[i][j-n]) printf("%d ",j-n);
    67         printf("\n");
    68     }
    69 }
    70 int main()
    71 {
    72     while(scanf("%d",&n)!=EOF)
    73     {
    74         read();
    75         go();
    76     }
    77     return 0;
    78 }
    没有人能阻止我前进的步伐,除了我自己!
  • 相关阅读:
    黄聪:VS中 "Duplicate items are not supported by the "Resources" parameter" 解决方法
    黄聪:新浪编辑器 SinaEditor
    黄聪:Delphi实现软件中登录用户的操作权限
    黄聪:Asp.Net性能优化
    黄聪:SQL Server 2005开窗函数的使用
    黄聪:Delphi 连接DBF数据
    黄聪:OpenGl 初级入门学习视频教程, 绘制一个立方体
    黄聪:再议.Net中null的使用规范
    黄聪:.NET开发中的Exception处理三定律[转]
    黄聪:SQL Server 开发之 复制表数据的SQL脚本生成器
  • 原文地址:https://www.cnblogs.com/proverbs/p/2662638.html
Copyright © 2020-2023  润新知