【网络流】——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,但是不知道为啥跑不了,可能是我太弱了。

猜你喜欢

转载自www.cnblogs.com/Nelson992770019/p/11354970.html
今日推荐