• [BZOJ] 1143: [CTSC2008]祭祀river


    题意:一张DAG上找出一些点,使得它们不能相互到达,求最大点数。

    也就是说,找DAG的最长反链,最长反链=n-最小链覆盖,拆点跑二分图最大匹配即可。

    注意先用Floyd传递闭包。

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<queue>
    
    using namespace std;
    
    inline int rd(){
      int ret=0,f=1;char c;
      while(c=getchar(),!isdigit(c))f=c=='-'?-1:1;
      while(isdigit(c))ret=ret*10+c-'0',c=getchar();
      return ret*f;
    }
    
    const int MAXN = 100005;
    const int INF=1<<30;
    
    struct Edge{
      int nxt,to,f;
    }e[MAXN<<1];
    int ecnt=1,head[MAXN],cur[MAXN];
    inline void add(int x,int y,int f){
      e[++ecnt].nxt = head[x];
      e[ecnt].to = y;
      e[ecnt].f = f;
      head[x] = ecnt;
    }
    
    int dep[MAXN];
    queue<int> Q;
    bool bfs(int S,int T){
      memset(dep,0,sizeof(dep));dep[S]=1;
      Q.push(S);
      while(!Q.empty()){
        int top=Q.front();Q.pop();
        for(int i=head[top];i;i=e[i].nxt){
          int v=e[i].to;
          if(dep[v]||!e[i].f)continue;
          dep[v]=dep[top]+1;
          Q.push(v);
        }
      }
      return dep[T];
    }
    int dfs(int x,int flow,int T){
      if(x==T)return flow;
      int used=0,tmp;
      for(int &i=cur[x];i;i=e[i].nxt){
        int v=e[i].to;
        if(dep[v]!=dep[x]+1)continue;
        tmp=dfs(v,min(flow-used,e[i].f),T);
        e[i].f-=tmp;e[i^1].f+=tmp;used+=tmp;
        if(used==flow)return flow;
      }
      if(!used)dep[x]=-1;
      return used;
    }
    
    int dinic(int S,int T){
      int ret=0;
      while(bfs(S,T)){memcpy(cur,head,sizeof(head));ret+=dfs(S,INF,T);}
      return ret;
    }
    
    int n,m;
    
    int a[105][105];
    
    int main(){
      n=rd();m=rd();
      int x,y;
      for(int i=1;i<=m;i++){
        x=rd();y=rd();
        a[x][y]=1;
      }
      for(int k=1;k<=n;k++){
        for(int i=1;i<=n;i++){
          for(int j=1;j<=n;j++){
            a[i][j]|=a[i][k]&&a[k][j];
          }
        }
      }
      for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
          if(!a[i][j])continue;
          add(i,j+n,1);add(j+n,i,0);
        }
      }
      int S=n+n+1,T=S+1;
      for(int i=1;i<=n;i++){
        add(S,i,1);add(i,S,0);
        add(i+n,T,1);add(T,i+n,0);
      }
      int ans=n-dinic(S,T);
      cout<<ans;
      return 0;
    }
    未经许可,禁止搬运。
  • 相关阅读:
    回调函数
    TFS(Team Foundation Server)介绍和入门
    android widget 开发实例 : 桌面便签程序的实现具体解释和源代码 (上)
    非常多人不愿意承认汉澳sinox已经超过windows
    vim: 自己定义颜色主题(colorscheme)
    银行家算法
    一道百度架构题
    select poll使用
    LDAPserver的安装
    在eclipse中启动tomcat时报错:could not create java virtual machine... a fatal error...
  • 原文地址:https://www.cnblogs.com/ghostcai/p/9646720.html
Copyright © 2020-2023  润新知