zoukankan      html  css  js  c++  java
  • [HihoCoder1394]网络流四·最小路径覆盖

    题目大意:
    从有向无环图中选出若干点不想交的链,使得这些链覆盖所有的点,并且链的条数最小。

    思路:
    设超级源点$S$、超级汇点$T$。
    将$N$个点复制一份,分为$A$部和$B$部。
    对于$A$部的所有点$A_i$,连一条从$S$到$A_i$的边;
    对于$B$部的所有点$B_i$,连一条从$B_i$到$T$的边。
    用最大流跑一边二分图匹配,得到的最大流F为每条链上入度为0的点的个数总和,而B部中未被匹配的点对应着每个链的头。
    答案即为N-F。

     1 #include<queue>
     2 #include<cstdio>
     3 #include<cctype>
     4 #include<vector>
     5 #include<cstring>
     6 inline int getint() {
     7     char ch;
     8     while(!isdigit(ch=getchar()));
     9     int x=ch^'0';
    10     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
    11     return x;
    12 }
    13 int s,t;
    14 const int E=42000,V=1002;
    15 struct Edge {
    16     int from,to;
    17     bool remain;
    18 };
    19 Edge e[E];
    20 std::vector<int> g[V];
    21 int sz=0;
    22 inline void add_edge(const int u,const int v,const bool w) {
    23     e[sz]=(Edge){u,v,w};
    24     g[u].push_back(sz);
    25     sz++;
    26 }
    27 int p[V];
    28 bool a[V];
    29 inline bool Augment() {
    30     memset(a,0,sizeof a);
    31     a[s]=true;
    32     std::queue<int> q;
    33     q.push(s);
    34     while(!q.empty()&&!a[t]) {
    35         int x=q.front();
    36         q.pop();
    37         for(unsigned i=0;i<g[x].size();i++) {
    38             Edge &y=e[g[x][i]];
    39             if(!a[y.to]&&y.remain) {
    40                 p[y.to]=g[x][i];
    41                 a[y.to]=a[x]&&y.remain;
    42                 q.push(y.to);
    43             }
    44         }
    45     }
    46     return a[t];
    47 }
    48 inline int EdmondsKarp() {
    49     int maxflow=0;
    50     while(Augment()) {
    51         for(int i=t;i!=s;i=e[p[i]].from) {
    52             e[p[i]].remain^=true;
    53             e[p[i]^1].remain^=true;
    54         }
    55         maxflow++;
    56     }
    57     return maxflow;
    58 }
    59 int main() {
    60     int n=getint(),m=getint();
    61     s=0,t=n<<1|1;
    62     for(int i=1;i<=n;i++) {
    63         add_edge(s,i,true);
    64         add_edge(i,s,false);
    65         add_edge(n+i,t,true);
    66         add_edge(t,n+i,false);
    67     }
    68     for(int i=1;i<=m;i++) {
    69         int u=getint(),v=getint();
    70         add_edge(u,n+v,true);
    71         add_edge(n+v,u,false);
    72     }
    73     printf("%d
    ",n-EdmondsKarp());
    74     return 0;
    75 }
  • 相关阅读:
    终于以一个ACMer的名义开通博客了。。
    Struts学习笔记一
    Matplotlib画图
    设计模式第一集——策略模式
    Hibernate学习笔记
    在linux下加python path【转】
    linux学习笔记
    C#3.0初体验
    asp.net中使用ffmpeg
    常用的正则表达式(经典)
  • 原文地址:https://www.cnblogs.com/skylee03/p/7252104.html
Copyright © 2011-2022 走看看