【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, flow; 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].flow = w; 21 head[u] = cnt; 22 23 edge[++cnt].next = head[v]; 24 edge[cnt].to = u; 25 edge[cnt].flow = 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].flow) 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].flow)))) 62 { 63 flow += f; 64 limit -= f; 65 edge[i].flow -= f; 66 edge[i^1].flow += 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].flow == 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].flow==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 }
隐约雷鸣,阴霾天空,但盼风雨来,能留你在此。
隐约雷鸣,阴霾天空,即使天无雨,我亦留此地。