• POJ 1904 King's Quest(强连通分量)


     

    题目大意

     

    一个国王,有 n(1<=n<=2000) 个儿子,在这个国家中有 n 个漂亮的妹子。每个儿子都有自己喜欢的妹子(可以是多个)。每个妹子只能嫁一个人,每个儿子只娶自己喜欢的人

    国王的巫师调查到了每个儿子喜欢哪些妹子,并且为每一个儿子分配了他喜欢的妹子让他娶

    但是国王不满意,说是要巫师统计出每个儿子能够娶哪些人,使得儿子们娶了这个妹子后,其他的每个儿子都有妹子可以娶

    题目给出了每个儿子喜欢的人,以及巫师做好的一个”妹子分配“方案

     

    好绕的题意~

     

    做法分析

     

    对于每个王子 A,假设他喜欢妹子 B,建边 <A, B>

    对于每个婚姻分配,比如王子 A 娶妹子 B,建边 <B, A>

    对建好的图缩点,处于同一个强连通分量重的王子和妹子可以混搭(前提是这个王子喜欢这个妹子)

    这道题挺神的,不知道为什么 AC 的人这么多,算了,POJ 上面题目的通过量向来很奇葩。。。

     

    参考代码

     

    POJ 1904
      1 #include <vector>
      2 #include <stack>
      3 #include <cstdio>
      4 #include <cstring>
      5 #include <iostream>
      6 #include <algorithm>
      7 
      8 using namespace std;
      9 
     10 const int N=4006;
     11 
     12 vector <int> arc[N], scc[N], ans[N];
     13 int n, T, ind;
     14 int dfn[N], low[N], id[N];
     15 stack <int> s;
     16 bool vs[N], love[N][N];
     17 
     18 void tarjan(int u)
     19 {
     20     s.push(u), vs[u]=1;
     21     dfn[u]=low[u]=T++;
     22     int len=(int)arc[u].size();
     23     for(int i=0; i<len; i++)
     24     {
     25         int v=arc[u][i];
     26         if(dfn[v]==-1)
     27         {
     28             tarjan(v);
     29             if(low[u]>low[v]) low[u]=low[v];
     30         }
     31         else if(vs[v] && low[u]>dfn[v]) low[u]=dfn[v];
     32     }
     33     if(low[u]==dfn[u])
     34     {
     35         for(int v; 1; )
     36         {
     37             v=s.top();
     38             s.pop(), vs[v]=0;
     39             scc[ind].push_back(v), id[v]=ind;
     40             if(v==u) break;
     41         }
     42         ind++;
     43     }
     44 }
     45 
     46 int main()
     47 {
     48     scanf("%d", &n);
     49     for(int i=1; i<=n; i++)
     50         for(int j=1; j<=n; j++)
     51             love[i][j]=0;
     52     for(int i=1, len, u; i<=n; i++)
     53     {
     54         scanf("%d", &len);
     55         arc[i].clear();
     56         for(int j=0; j<len; j++)
     57         {
     58             scanf("%d", &u);
     59             arc[i].push_back(n+u);
     60             love[i][u]=1;
     61         }
     62     }
     63     for(int i=1, u; i<=n; i++)
     64     {
     65         scanf("%d", &u);
     66         arc[u+n].push_back(i);
     67     }
     68     for(int i=1; i<=n+n; i++) vs[i]=0, dfn[i]=-1, scc[i].clear();
     69     while(!s.empty()) s.pop();
     70     ind=T=0;
     71     for(int i=1; i<=n+n; i++) if(dfn[i]==-1) tarjan(i);
     72     for(int i=0; i<ind; i++) sort(scc[i].begin(), scc[i].end());
     73     for(int i=1; i<=n; i++) ans[i].clear();
     74     for(int i=1; i<=n; i++)
     75     {
     76         int u=id[i];
     77         int L=0, R=(int)scc[u].size()-1;
     78         int len=R+1;
     79         while(L<R)
     80         {
     81             int mid=(L+R)>>1;
     82             if(scc[u][mid]<=n) L=mid+1;
     83             else R=mid;
     84         }
     85         if(scc[u][L]<=n) L++;
     86         for(int j=L; j<len; j++)
     87         {
     88             if(!love[i][scc[u][j]-n]) continue;
     89             ans[i].push_back(scc[u][j]-n);
     90         }
     91     }
     92     for(int i=1; i<=n; i++)
     93     {
     94         int len=(int)ans[i].size();
     95         printf("%d ", len);
     96         for(int j=0; j<len; j++)
     97         {
     98             printf("%d", ans[i][j]);
     99             if(j==len-1) printf("\n"); else printf(" ");
    100         }
    101     }
    102     return 0;
    103 }

    AC通道

    POJ 1904 King's Quest

  • 相关阅读:
    B-线性代数-距离公式汇总
    B-线性代数-范数
    B-线性代数-矩阵转置
    B-概率论-贝叶斯决策
    B-概率论-极大似然估计
    B-概率论-条件概率
    2018.1.7java转型
    追求
    面向心态
    数据类型和type函数
  • 原文地址:https://www.cnblogs.com/zhj5chengfeng/p/2963619.html
Copyright © 2020-2023  润新知