• Bzoj 2718: [Violet 4]毕业旅行 && Bzoj 1143: [CTSC2008]祭祀river 传递闭包,二分图匹配,匈牙利,bitset


    1143: [CTSC2008]祭祀river

    Time Limit: 10 Sec  Memory Limit: 162 MB
    Submit: 1878  Solved: 937
    [Submit][Status][Discuss]

    Description

    在遥远的东方,有一个神秘的民族,自称Y族。他们世代居住在水面上,奉龙王为神。每逢重大庆典, Y族都会在水面上举办盛大的祭祀活动。我们可以把Y族居住地水系看成一个由岔口和河道组成的网络。每条河道连接着两个岔口,并且水在河道内按照一个固定的方向流动。显然,水系中不会有环流(下图描述一个环流的例子)。

     

    由于人数众多的原因,Y族的祭祀活动会在多个岔口上同时举行。出于对龙王的尊重,这些祭祀地点的选择必须非常慎重。准确地说,Y族人认为,如果水流可以从一个祭祀点流到另外一个祭祀点,那么祭祀就会失去它神圣的意义。族长希望在保持祭祀神圣性的基础上,选择尽可能多的祭祀的地点。

    Input

    第一行包含两个用空格隔开的整数N、M,分别表示岔口和河道的数目,岔口从1到N编号。接下来M行,每行包含两个用空格隔开的整数u、v,描述一条连接岔口u和岔口v的河道,水流方向为自u向v。

    Output

    第一行包含一个整数K,表示最多能选取的祭祀点的个数。

    Sample Input

    4 4
    1 2
    3 4
    3 2
    4 2

    Sample Output

    2

    【样例说明】
    在样例给出的水系中,不存在一种方法能够选择三个或者三个以上的祭祀点。包含两个祭祀点的测试点的方案有两种:
    选择岔口1与岔口3(如样例输出第二行),选择岔口1与岔口4。
    水流可以从任意岔口流至岔口2。如果在岔口2建立祭祀点,那么任意其他岔口都不能建立祭祀点
    但是在最优的一种祭祀点的选取方案中我们可以建立两个祭祀点,所以岔口2不能建立祭祀点。对于其他岔口
    至少存在一个最优方案选择该岔口为祭祀点,所以输出为1011。

    HINT

    对于每个测试点:如果你仅输出了正确的被选取的祭祀点个数,那么你将得到该测试点30%的分数;如果你仅输出了正确的被选取的祭祀点个数与一个可行的方案,那么你将得到该测试点60%的分数;如果你的输出完全正确,那么你将得到该测试点100%的分数


    【数据规模】 N ≤ 100 M ≤ 1 000

    Source

     题解:
    这道题转化一下,就成了我们要找最大独立集。
    最大独立集=二分图点数-最小点覆盖=最长反链长度=最小链覆盖(路径不能相交)
    链为一些点的集合,链上任意两点x,y, 要么x能到达y,要么y能到达x。
    反链为一些点的集合,链上任意两点x,y, x不能到达y且y不能到达x。
    然后我们就跑个传递闭包,把x能到达y的处理出来。
    然后重新构图,将x能到达y的连起来。跑个最大匹配,再用总点数减去最大匹配数即可。。。
    Dinic和匈牙利 都可以过。。。
    我写的是匈牙利:
     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 bitset<110> a[110];
     4 bitset<110> vis;
     5 int bf[110],n,f[110][110];
     6 int read()
     7 {
     8     int s=0,fh=1;char ch=getchar();
     9     while(ch<'0'||ch>'9'){if(ch=='-')fh=-1;ch=getchar();}
    10     while(ch>='0'&&ch<='9'){s=s*10+(ch-'0');ch=getchar();}
    11     return s*fh;
    12 }
    13 int xyl(int u)
    14 {
    15     int v;
    16     for(v=1;v<=n;v++)
    17     {
    18         if(a[u][v]!=0&&vis[v]==0)
    19         {
    20             vis[v]=1;
    21             if(xyl(bf[v])==1||bf[v]==0)
    22             {
    23                 bf[v]=u;
    24                 return 1;
    25             }
    26         }
    27     }
    28     return 0;
    29 }
    30 int main()
    31 {
    32     int m,i,j,x,y,ans;
    33     n=read();m=read();
    34     //for(i=1;i<=n;i++)a[i][i]=1;
    35     for(i=1;i<=m;i++)
    36     {
    37         x=read();y=read();
    38         a[x][y]=1;
    39     }
    40     for(i=1;i<=n;i++)
    41     {
    42         for(j=1;j<=n;j++)
    43         {
    44             if(a[j][i])a[j]|=a[i];
    45         }
    46     }
    47     /*for(i=1;i<=n;i++)
    48     {
    49         for(j=1;j<=n;j++)
    50         {
    51             if(a[i][j]&&i!=j)f[i][j]=1;
    52         }
    53     }*/
    54     memset(bf,0,sizeof(bf));
    55     ans=0;
    56     for(i=1;i<=n;i++)
    57     {
    58         vis.reset();
    59         ans+=xyl(i);
    60     }
    61     printf("%d",n-ans);
    62     fclose(stdin);
    63     fclose(stdout);
    64     return 0;
    65 }
    View Code
  • 相关阅读:
    [bzoj1731] [Usaco2005 dec]Layout 排队布局
    [bzoj1914] [Usaco2010 OPen]Triangle Counting 数三角形
    [bzoj1774] [Usaco2009 Dec]Toll 过路费
    [bzoj1783] [Usaco2010 Jan]Taking Turns
    [bzoj1705] [Usaco2007 Nov]Telephone Wire 架设电话线
    [bzoj1700]: [Usaco2007 Jan]Problem Solving 解题
    定时启动任务
    数据库表转javaBean
    验证码的生成
    MD5加密与验证
  • 原文地址:https://www.cnblogs.com/Var123/p/5281942.html
Copyright © 2020-2023  润新知