• [bzoj1143]祭祀


    求最长反链(链上任意两个点不连通),可以发现,最长反链=最小链覆盖(因为每一条链都最多只有一个点入选),而DAG的最小链覆盖也就是最小路径覆盖(可相交)。然后floyd传递闭包,将任意两个连通的点都连一条边,这样就变成不可相交的最小路径覆盖(可以绕过去)。

    不可相交的最小路径覆盖:将每一个点裂成两个点,分别处理出边和入边,形成二分图,二分图上的每一个匹配意味着答案-1,因此n-最大匹配数。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define N 205
     4 struct ji{
     5     int nex,to;
     6 }edge[N*N];
     7 int E,n,m,x,y,ans,head[N],vis[N],flag[N],f[N][N];
     8 void add(int x,int y){
     9     edge[E].nex=head[x];
    10     edge[E].to=y;
    11     head[x]=E++;
    12 }
    13 bool dfs(int k){
    14     if (vis[k])return 0;
    15     vis[k]=1;
    16     for(int i=head[k];i!=-1;i=edge[i].nex){
    17         int v=edge[i].to;
    18         if ((!flag[v])||(dfs(flag[v]))){
    19             flag[k]=v;
    20             flag[v]=k;
    21             return 1;
    22         }
    23     }
    24     return 0;
    25 }
    26 int main(){
    27     scanf("%d%d",&n,&m);
    28     memset(head,-1,sizeof(head));
    29     for(int i=1;i<=m;i++){
    30         scanf("%d%d",&x,&y);
    31         f[x][y]=1;
    32     }
    33     for(int i=1;i<=n;i++)
    34         for(int j=1;j<=n;j++)
    35             for(int k=1;k<=n;k++)
    36                 f[j][k]|=((f[j][i])&(f[i][k]));
    37     for(int i=1;i<=n;i++)
    38         for(int j=1;j<=n;j++)
    39             if (f[i][j])add(i,j+n);
    40     ans=n;
    41     for(int i=1;i<=n;i++){
    42         memset(vis,0,sizeof(vis));
    43         if (!flag[i])ans-=dfs(i);
    44     }
    45     printf("%d",ans);
    46 }
    View Code
  • 相关阅读:
    20165105 学习基础和C语言基础调查
    2017-2018网络攻防第四周作业
    2017-2018-2 20165233 实验三 敏捷开发与XP实践
    20165233 2017-2018-2 《Java程序设计》第九周学习总结
    Linux学习笔记(一)
    第三周学习总结
    数据结构C++,线性表学习
    uname()系统调用学习
    cd
    go连接数据库并执行文件中的sql语句
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/11247987.html
Copyright © 2020-2023  润新知