[bzoj1143]祭祀
Posted pywbktda
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[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
以上是关于[bzoj1143]祭祀的主要内容,如果未能解决你的问题,请参考以下文章