码迷,mamicode.com
首页 > 其他好文 > 详细

bzoj1143[CTSC2008]祭祀river

时间:2016-07-21 21:53:26      阅读:198      评论:0      收藏:0      [点我收藏+]

标签:

bzoj1143[CTSC2008]祭祀river

题意:

Y族居住地水系是一个由岔口和河道组成的网络。每条河道连接着两个岔口,并且水在河道内按照一个固定的方向流动。水系中不会有环流。由于人数众多的原因,Y族的祭祀活动会在多个岔口上同时举行。Y族人认为,如果水流可以从一个祭祀点流到另外一个祭祀点,那么祭祀就会失去它神圣的意义。求保持祭祀神圣性的基础上祭祀的地点数目的最大值。

题解:

利用各种性质。首先,题目的模型被称为最长反链,即在有向无环图中求一个点集使其两两不可达。Dilworth定理:最长反链长度=最小链覆盖(用最少的链覆盖所有节点)(证明:http://vfleaking.blog.163.com/blog/static/1748076342012918105514527/%vfk大神然而我看不懂)。求最小链覆盖的方法:建一个二分图,如果点a、b可达,则将左边的a与右边的边相连,求最大独立集。然后又有最大独立集=点数n(指二分图的半边的点数)-二分图最大匹配。

代码:

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 #include <queue>
 5 #define INF 0x3fffffff
 6 #define inc(i,j,k) for(int i=j;i<=k;i++)
 7 using namespace std;
 8 
 9 int n,m,a[200][200],s,t;
10 struct e{int t,c,n;}; e es[100000]; int ess,g[1000];
11 inline void pe(int f,int t,int c){
12     es[++ess]=(e){t,c,g[f]};g[f]=ess;es[++ess]=(e){f,0,g[t]};g[t]=ess;
13 }
14 void init(){ess=-1; memset(g,-1,sizeof(g));}
15 queue <int> q; int h[1000];
16 bool bfs(int s,int t){
17     while(! q.empty())q.pop(); memset(h,-1,sizeof(h)); h[s]=0; q.push(s);
18     while(! q.empty()){
19         int x=q.front(); q.pop();
20         for(int i=g[x];i!=-1;i=es[i].n)if(es[i].c&&h[es[i].t]==-1)h[es[i].t]=h[x]+1,q.push(es[i].t);
21     }
22     if(h[t]==-1)return 0;else return 1;
23 }
24 int dfs(int x,int t,int f){
25     if(x==t)return f; int used=0;
26     for(int i=g[x];i!=-1;i=es[i].n)if(es[i].c&&h[es[i].t]==h[x]+1){
27         int w=dfs(es[i].t,t,min(f,es[i].c));
28         es[i].c-=w; es[i^1].c+=w; used+=w; f-=w; if(f==0)return used;
29     }
30     if(used==0)h[x]=-1; return used;
31 }
32 int dinic(int s,int t){int ans=0; while(bfs(s,t))ans+=dfs(s,t,INF); return ans;};
33 int main(){
34     scanf("%d%d",&n,&m); memset(a,0,sizeof(a));
35     inc(i,1,m){int a1,b1; scanf("%d%d",&a1,&b1); a[a1][b1]=1;}
36     inc(k,1,n)inc(i,1,n)inc(j,1,n)a[i][j]|=a[i][k]&a[k][j];
37     s=0; t=n+n+1; init();
38     inc(i,1,n)pe(s,i,1),pe(i+n,t,1);
39     inc(i,1,n)inc(j,1,n)if(a[i][j])pe(i,j+n,1);
40     printf("%d",n-dinic(s,t));
41 }

 

20160701

bzoj1143[CTSC2008]祭祀river

标签:

原文地址:http://www.cnblogs.com/YuanZiming/p/5693035.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!