zoukankan      html  css  js  c++  java
  • bzoj1143[CTSC2008]祭祀river

    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

  • 相关阅读:
    别逃避,是时候来给JVM一记重锤了
    从CAS讲起,真正高性能解决并发编程的原子操作
    深入理解typedef
    【Valse首发】CNN的近期进展与实用技巧(上)
    基于深度学习的目标检测研究进展
    全卷积网络:从图像级理解到像素级理解
    产生式与判别式模型
    游戏后台杂谈:后台的语言、系统与构架
    优化人脸检测网络
    最长的回文子序列
  • 原文地址:https://www.cnblogs.com/YuanZiming/p/5693035.html
Copyright © 2011-2022 走看看