• 【网络流】——P2764 最小路径覆盖问题


    一个最小路径覆盖的模板题。

    Go:洛谷

    • 最小路径覆盖=顶点数-二分图最大匹配
    • 因此我们将点复制一份,按照题目给的数据在两端连边,长度为1。
    • 建立一个super源&汇,源向左边的点连边,右边的点向汇连边,长度为1。
    • 求解路径:
    • 我们在邻接表中存下每条边的起始点,对于一条流为0的边,表示它是最小路径中的一条,那么用冰茶姬将他们连起来,最后访问单独集合中的路径即可。
      1 #include <bits/stdc++.h>
      2 using namespace std;
      3 const int N = 6e5+10,inf = 1e9;
      4 int n, m, S, T, ans, d[N],head[N],maxflow,vis[N],f[N];
      5 int tot=-1;
      6 struct edge{
      7     int w;
      8     int next;
      9     int to;
     10     int from;
     11 }e[N];
     12 int getf(int x){
     13     return f[x]==x?f[x]:f[x]=getf(f[x]);
     14 }
     15 inline void addedge(int x, int y, int z) {
     16     e[++tot].to=y;
     17     e[tot].next=head[x];
     18     e[tot].w=z;
     19     e[tot].from=x;
     20     head[x]=tot;
     21 }//建图 
     22 int pos(int x,int y){
     23     return (x-1)*n+y;
     24 }
     25 inline bool bfs() {
     26     memset(d, 0, sizeof(d));
     27     queue<int> q;
     28     q.push(S);
     29     d[S] = 1;
     30     while (q.size()) {
     31         int x = q.front();
     32         q.pop();
     33         for (int i = head[x]; i!=-1; i = e[i].next) {
     34             int y = e[i].to, z = e[i].w;
     35             if (d[y] || !z) continue;
     36             q.push(y);
     37             d[y] = d[x] + 1;
     38             if (y == T) return 1;
     39         }
     40     }
     41     return 0;
     42 }
     43 
     44 int dinic(int x, int flow) {
     45     if (x == T) return flow;
     46     int rest = flow;
     47     for (int i = head[x]; i!=-1 && rest; i = e[i].next) {
     48         int y = e[i].to, z = e[i].w;
     49         if (d[y] != d[x] + 1 || !z) continue;
     50         int k = dinic(y, min(rest, z));
     51         if (!k) d[y] = 0;
     52         else {
     53             e[i].w -= k;
     54             e[i^1].w += k;
     55             rest -= k;
     56         }
     57     }
     58     return flow - rest;
     59 }
     60 void dfs2(int u){
     61     printf("%d ",u);
     62     for(int i=head[u];i!=-1;i=e[i].next){
     63         if(e[i].w==0&&e[i].to>n) dfs2(e[i].to-n);
     64     }
     65 }
     66 void solve(){
     67     int now=0;
     68     while(bfs()){
     69         while(now=dinic(S,inf))
     70             maxflow+=now;
     71     }
     72 }
     73 int main() {
     74     memset(head,-1,sizeof(head));
     75     scanf("%d%d",&n,&m);
     76     S=0,T=n*2+1;
     77     int x,y;
     78     for(int i=1;i<=m;i++){
     79         scanf("%d%d",&x,&y);
     80         addedge(x,y+n,1);
     81         addedge(y+n,x,0);
     82     }
     83     for(int i=1;i<=n;i++){
     84         addedge(S,i,1);
     85         addedge(i,S,0);
     86         addedge(n+i,T,1);
     87         addedge(T,n+i,0);
     88     }
     89     solve();
     90     for(int i=1;i<=n;i++) f[i]=i;
     91     for(int i=0;i<=tot;i++){
     92         if(e[i].from>=1&&e[i].from<=n&&e[i].to>n&&e[i].to<T&&!e[i].w) f[getf(e[i].to-n)]=getf(e[i].from);
     93     }
     94     for(int i=1;i<=n;i++){
     95         if(f[i]==i){
     96             dfs2(i);
     97             printf("\n");
     98         } 
     99     }
    100     printf("%d",n-maxflow);
    101     return 0;
    102 }

    注:原来想用我的优化版dinic,但是不知道为啥跑不了,可能是我太弱了。

    ——抓住了时间,却不会利用的人,终究也逃不过失败的命运。
  • 相关阅读:
    自己奋斗才有用,人要坚持到成功为止
    自己需要的都是靠自己争取,人生只有自己才靠得住
    不如意也是要过日子,人是不可能和天斗的
    懂得满足也是好的,人要学会知足才会感到幸福
    不要让自己有后悔的时候,人都是要不负自己的青春年少
    ES6 の 块级作用域
    javascript中this的指向分析
    let & var 的区别
    npm 全局安装环境配置
    visibilitychange => 获取页面的可见性
  • 原文地址:https://www.cnblogs.com/Nelson992770019/p/11354970.html
Copyright © 2020-2023  润新知