【洛谷 P2764】 最小路径覆盖问题(最大流)

题目链接
首先有(n)条路径,每条路径就是一个点,然后尽量合并,答案就是点数-合并数。
套路拆点,源连入,出连汇,原有的边入出连。
最大流就是最大合并数,第一问解决。
然后怎么输出方案?
我是找到所有路径中的最后一个点,然后根据残量网络一直往前跳,(dfs)倒序输出。

#include <cstdio>
#include <queue>
#include <cstdlib>
#include <cstring>
#define INF 2147483647
using namespace std;
const int MAXN = 360;
const int MAXM = 16010;
struct point{
    int x, y, time;
}Now;
queue <int> q;
struct Edge{
    int from, to, next, rest;
}e[MAXM];
int head[MAXN], num = 1, s, t, now, n, m, dis[MAXN], a, b;
inline void Add(int from, int to, int flow){
    e[++num] = (Edge){ from, to, head[from], flow }; head[from] = num;
    e[++num] = (Edge){ to, from, head[to], 0 }; head[to] = num;
}
int re(){
    memset(dis, 0, sizeof dis);
    q.push(s); dis[s] = 1;
    while(q.size()){
    	now = q.front(); q.pop();
    	for(int i = head[now]; i; i = e[i].next)
    	   if(e[i].rest && !dis[e[i].to])
    	     dis[e[i].to] = dis[now] + 1, q.push(e[i].to);
    }
    return dis[t];
}
int find(int u, int flow){
    if(u == t || !flow) return flow;
    int sum = 0, T;
    for(int i = head[u]; i; i = e[i].next)
       if(e[i].rest && dis[e[i].to] == dis[u] + 1){
       	 T = find(e[i].to, min(flow - sum, e[i].rest));
         e[i].rest -= T; e[i ^ 1].rest += T; sum += T;
       }
    if(!sum) dis[u] = 0;
    return sum;
}
int dinic(){
    int ans = 0;
    while(re()) ans += find(s, INF);
    return ans;
}
void dfs(int u){
	for(int i = head[u + n]; i; i = e[i].next)
	   if(e[i].to <= n && e[i].rest)
	     dfs(e[i].to);
	printf("%d ", u);
}
int ans;
int main(){
    scanf("%d%d", &n, &m); s = 345; t = 350;
    for(int i = 1; i <= m; ++i){
       scanf("%d%d", &a, &b);
       Add(a, b + n, 1);
    }
    for(int i = 1; i <= n; ++i)
       Add(s, i, 1), Add(i + n, t, 1);
    ans = n - dinic();
    for(int i = 1; i <= n; ++i){
    	int flag = 1;
    	for(int j = head[i]; j; j = e[j].next)
    	   if(e[j].to > n && e[j].to <= 2 * n && !e[j].rest){
    	   	 flag = 0; break;
    	   }
    	if(flag) dfs(i),
    	putchar('
');
    }
    printf("%d
", ans);
    return 0;
}
原文地址:https://www.cnblogs.com/Qihoo360/p/10541461.html