• 【建模+强连通分量】POJ1904 King's Quest


    Description

    一个国王有n个王子,同时有n个女孩。每个王子都有自己喜欢的若干个女孩,现给定一个合法的完备匹配(也就是一个王子娶其中一个自己喜欢女孩),求每个王子可以选择哪些女孩可以让剩下的每个王子依旧能够选择到自己喜欢的一个女孩。

    Solution

    对于给定的排列,我们设ai为男a对应的女生,bi为女b对应的男生。

    男i可以选哪些女生?选ai显然是可以的,如果没有选ai而选的x,那么会造成两个影响,x有两个a和bx选,ai没有人选。

    所以需要让bx选新的女生,如果bx能选到ai,那么问题就解决了,否则bx就只能选一个y,让by继续选...直到能选到ai。若总走不到ai,则x不能被选。

    这也就是说,从x能走到ai,如果我们这样建图,所有男向喜欢的女连一条边,根据给定匹配由女向男连边,那么i可以选x,也就是x可以到i。

    因为i喜欢x,i定可到x,于是他们必在一个强连通分量中。

    得到具体做法,按照上述建图,如果x和i在一个强连通分量,且i喜欢x,x就可以选i,问题解决。

    Code

     1 #include<cstdio>
     2 #include<algorithm>
     3 using namespace std;
     4 const int maxn=2005;
     5 
     6 int pre[maxn*2],low[maxn*2],clock;
     7 int scc[maxn*2],cnt,s[maxn*2],c;
     8 int G[maxn][maxn];
     9 int head[maxn*2],e[maxn*maxn],nxt[maxn*maxn],k;
    10 int adde(int u,int v){
    11     e[++k]=v;nxt[k]=head[u];head[u]=k;
    12 }
    13 int n;
    14 
    15 int dfs(int u){
    16     pre[u]=low[u]=++clock;
    17     s[++c]=u;
    18     for(int i=head[u];i;i=nxt[i]){
    19         int v=e[i];
    20         if(!pre[v]){
    21             dfs(v);
    22             low[u]=min(low[v],low[u]);
    23         }
    24         if(!scc[v]){
    25             low[u]=min(pre[v],low[u]);
    26         }
    27     }
    28     if(pre[u]==low[u]){
    29         cnt++;
    30         while(c){
    31             scc[s[c]]=cnt;
    32             if(s[c--]==u) break;
    33         }
    34     }
    35 }
    36 
    37 int main(){
    38     int x,t;
    39     scanf("%d",&n);
    40     for(int i=1;i<=n;i++){
    41         scanf("%d",&t);
    42         for(int j=1;j<=t;j++){
    43             scanf("%d",&x);
    44             adde(i,x+n);
    45             G[i][x]=1;
    46         }
    47     }
    48     for(int i=1;i<=n;i++){
    49         scanf("%d",&x);
    50         adde(x+n,i);
    51     }
    52     
    53     for(int i=1;i<=2*n;i++)
    54         if(!pre[i]) dfs(i);
    55         
    56     for(int i=1;i<=n;i++){
    57         int tot=0;
    58         for(int j=n+1;j<=2*n;j++)
    59             if(G[i][j-n]&&scc[i]==scc[j]) tot++;
    60         printf("%d ",tot);
    61         for(int j=n+1;j<=2*n;j++)
    62             if(G[i][j-n]&&scc[i]==scc[j]) printf("%d ",j-n);
    63         printf("
    ");
    64     }
    65     return 0;
    66 }
  • 相关阅读:
    nginx的root和alias详解
    nginx location匹配细节讲解
    nginx的域名访问和路径结尾斜杠问题
    redis知识点入门
    nodepad++未保存文件的内容安不安全?
    secureCRT或Xshell的隧道转发详解
    XXE漏洞示例讲解
    内核Hash表hlist Hello
    tracer ftrace笔记(6)—— SQL查询 Hello
    MTK Powerhal 学习笔记 Hello
  • 原文地址:https://www.cnblogs.com/xkui/p/4556832.html
Copyright © 2020-2023  润新知