bzoj1143[CTSC2008] 祭祀river

来源:互联网 发布:电视剧回看用什么软件 编辑:程序博客网 时间:2024/06/10 02:23

题目链接:bzoj1143

题目大意:

n个点m条有向边(保证无环)。要求选最多的点,使该点集中每个点都不能到达点集中的其他点。


题解:

最长反链

我觉得能想到匈牙利好厉害啊。根本不会往哪方面想。。。
因为有个背景知识...最长反链与最小链覆盖
大概可以看看这个http://vfleaking.blog.163.com/blog/static/1748076342012918105514527/
所以这道题就是裸的求最长反链=最小链覆盖。而求最小链覆盖数的方法就是首先传递闭包,然后就变成了最小路径覆盖。拆点,用二分图匹配解决。
因为n<=100很小,所以直接floyd搞就好了。

#include<cstdio>#include<cstdlib>#include<cstring>#include<iostream>#include<algorithm>using namespace std;#define maxn 110bool bo[maxn][maxn];int n,ask[maxn],bf[maxn],tim;int ffind(int x){for (int i=1;i<=n;i++) if (bo[x][i] && ask[i]!=tim)  {ask[i]=tim;if (bf[i]==-1 || ffind(bf[i])){bf[i]=x;return true;} }return false;}int main(){//freopen("a.in","r",stdin);//freopen("a.out","w",stdout);int m,i,j,k,x,y,sum,ans;scanf("%d%d",&n,&m);memset(bo,false,sizeof(bo));for (i=1;i<=m;i++){scanf("%d%d",&x,&y);bo[x][y]=true;}for (k=1;k<=n;k++)  for (i=1;i<=n;i++)  for (j=1;j<=n;j++) if (i!=j)   if (i!=k && j!=k)if (bo[i][k] && bo[k][j]) bo[i][j]=true;ans=tim=0;memset(ask,0,sizeof(ask));memset(bf,-1,sizeof(bf));for (i=1;i<=n;i++){tim++;if (ffind(i)) ans++;}ans=n-ans;printf("%d\n",ans);return 0;}


0 0
原创粉丝点击