【luogu P2764 最小路径覆盖问题】 题解

题目链接:https://www.luogu.org/problemnew/show/P2764

把每个点在左边建一遍右边建一遍,再加上源点汇点,跑最大流,n-最大流就是答案。

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <algorithm>
  4 #include <queue>
  5 #include <cstring>
  6 using namespace std;
  7 const int inf = 1e9;
  8 const int maxn = 1000010;
  9 int n, m, s, t, deep[maxn], maxflow, pre[maxn], st;
 10 struct EDG{
 11     int next, to, dis;
 12 }edge[maxn];
 13 int cnt = -1, head[maxn], cur[maxn];
 14 queue<int> q;
 15 
 16 void add(int u, int v, int w)
 17 {
 18     edge[++cnt].next = head[u];
 19     edge[cnt].to = v;
 20     edge[cnt].dis = w;
 21     head[u] = cnt;
 22     
 23     edge[++cnt].next = head[v];
 24     edge[cnt].to = u;
 25     edge[cnt].dis = 0;
 26     head[v] = cnt;
 27 }
 28 
 29 bool bfs(int s, int t)
 30 {
 31     for(int i = s; i <= t; i++) 
 32     {
 33         cur[i] = head[i];
 34         deep[i] = 0;
 35     }
 36     deep[s] = 1;
 37     queue<int> q;
 38     q.push(s);
 39     while(!q.empty())
 40     {
 41         int now = q.front(); q.pop();
 42         for(int i = head[now]; i != -1; i = edge[i].next)
 43         {
 44             if(!deep[edge[i].to] && edge[i].dis)
 45             {
 46                 q.push(edge[i].to);
 47                 deep[edge[i].to] = deep[now]+1;
 48             }
 49         }
 50     }
 51     if(deep[t]) return true;
 52     return false;
 53 }
 54 int dfs(int now, int t, int limit)
 55 {
 56     if(!limit || now == t) return limit;
 57     int flow = 0, f;
 58     for(int i = cur[now]; i != -1; i = edge[i].next)
 59     {
 60         cur[now] = i;
 61         if(deep[edge[i].to] == deep[now]+1 && (f = dfs(edge[i].to, t, min(limit, edge[i].dis))))
 62         {
 63             flow += f;
 64             limit -= f;
 65             edge[i].dis -= f;
 66             edge[i^1].dis += f;
 67             if(!limit) break;
 68         }
 69     }
 70     return flow;
 71 }
 72 void Dinic(int s, int t)
 73 {
 74     while(bfs(s,t))
 75     maxflow += dfs(s,t,inf);
 76 }
 77 void output(int x)
 78 {
 79     printf("%d ",x);
 80     for(int i = head[x]; i != -1; i = edge[i].next)
 81     {
 82         if(edge[i].dis == 0 && edge[i].to - n > 0 && edge[i].to - n <= n)
 83         {
 84             output(edge[i].to - n);
 85             break;
 86         }
 87     }
 88     return ;
 89 }
 90 int main()
 91 {
 92     scanf("%d%d",&n,&m);
 93     for(int i = 0; i <= 2*n+1; i++)
 94     head[i] = -1;
 95     s = 0, t = 2*n+1;
 96     for(int i = 1; i <= m; i++)
 97     {
 98         int u, v;
 99         scanf("%d%d",&u,&v);
100         add(u,v+n,1);
101     }
102     for(int i = 1; i <= n; i++)
103     {
104         add(0,i,1);
105         add(i+n,2*n+1,1);
106     }
107     Dinic(s,t);
108     for(int i=head[2*n+1];i!=-1;i=edge[i].next)
109     {
110         if(edge[i^1].dis==1)
111             pre[++st]=edge[i].to;
112     }
113     for(int i=1;i<=st;i++)
114     {
115         output(pre[i]-n);
116         printf("\n");
117     }
118     printf("%d",n - maxflow);
119     return 0;
120 }

猜你喜欢

转载自www.cnblogs.com/MisakaAzusa/p/9038206.html