Loj 6002 最小路径覆盖(最大流)

题意:

求不相交的最小路径覆盖

思路:

连边跑二分图,匹配一条边相当于缩了一条边,答案为n-maxflow

如果是求可以相交的最小路径覆盖的话,先用Floyd跑出可达矩阵,然后所有可达的点连边跑二分图即可

代码:

这个dinic板子加边前要tot=1,否则每一对正反向流会乱掉

由于本题要输出方案,这里有两份代码,一份是跑最大流的时候记录流向,另一份是根据残余网络纪录流向

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <string>
#include <stack>
#include <queue>
#include <deque>
#include <set>
#include <vector>
#include <ctime>
#include <map>

#define fst first
#define sc second
#define pb push_back
#define mem(a, b) memset(a, b, sizeof(a))
#define lson l, mid, root << 1
#define rson mid + 1, r, root << 1 | 1
#define lc root << 1
#define rc root << 1 | 1
#define lowbit(x) ((x) & (-x))

using namespace std;

typedef double db;
typedef long double ldb;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> PI;
typedef pair<ll, ll> PLL;

const db eps = 1e-6;
const int mod = 1e9 + 7;
const int maxn = 4e4 + 100;
const int maxm = 4e5 + 100;
const int inf = 0x3f3f3f3f;
const db pi = acos(-1.0);

int head[maxn], d[maxn];                //
int ver[maxm], edge[maxm], Next[maxm];  // edge[i]: c for edge_i
int n, m, s, t, tot, maxflow;
queue<int> q;
int st[maxn];
void add(int x, int y, int z) {
    ver[++tot] = y, edge[tot] = z, Next[tot] = head[x], head[x] = tot;
    st[tot]=x;
    ver[++tot] = x, edge[tot] = 0, Next[tot] = head[y], head[y] = tot;
    st[tot]=y;
}
int du[maxn];
bool bfs() {
    mem(d, 0);
    while (!q.empty()) q.pop();
    q.push(s);
    d[s] = 1;
    while (!q.empty()) {
        int x = q.front();
        q.pop();
        for (int i = head[x]; i; i = Next[i]) {
            if (edge[i] && !d[ver[i]]) {
                q.push(ver[i]);
                d[ver[i]] = d[x] + 1;
                if (ver[i] == t)
                    return true;
            }
        }
    }
    return false;
}
int nx[maxn];
int dinic(int x, int flow) {
    if (x == t)
        return flow;
    int rest = flow, k;
    for (int i = head[x]; i; i = Next[i]) {
        if (edge[i] && d[ver[i]] == d[x] + 1) {
            k = dinic(ver[i], min(rest, edge[i]));
            if (!k) {
                d[ver[i]] = 0;
            } else {
                edge[i] -= k;
                edge[i ^ 1] += k;
                rest -= k;
            }
        }
    }
    return flow - rest;
}
int vis[maxn];
int pre[maxn];
int main() {
    mem(pre, -1);
    mem(nx,-1);
    s = 0;
    t = 1;
    tot = 1;
    scanf("%d %d", &n, &m);
    for (int i = 1; i <= m; i++) {
        int x, y;
        scanf("%d %d", &x, &y);
        x *= 2;
        y *= 2;
        add(x, y + 1, 1);
    }
    for (int i = 1; i <= n; i++) {
        add(s, i * 2, 1);
        add(i * 2 + 1, t, 1);
    }
    int maxflow = 0;
    int flow;
    while (bfs()) {
        while (1) {
            flow = dinic(s, inf);
            if (flow == 0)
                break;
            maxflow += flow;
        }
    }
    for(int i = 2; i <= tot; i++){
        if(edge[i]==0&&st[i]%2==0&&st[i]>=2&&st[i]<=2*n&&ver[i]!=s){
            int x = st[i]/2;
            int y = (ver[i]-1)/2;
            //printf("%d %d\n",x,y);
            pre[y] = x;
            nx[x] = y;
        }
    }
    for(int i = 1; i <= n; i++){
        if(pre[i]==-1){
            int x = i;
            while(x!=-1){
                printf("%d ", x);
                x= nx[x];
            }
            printf("\n");
        }
    }
    printf("%d\n", n - maxflow);
    return 0;
}

/*
5 3
1 2 3 4 5
1 2 3
2 1 4
4 3 5
 */
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <string>
#include <stack>
#include <queue>
#include <deque>
#include <set>
#include <vector>
#include <ctime>
#include <map>

#define fst first
#define sc second
#define pb push_back
#define mem(a, b) memset(a, b, sizeof(a))
#define lson l, mid, root << 1
#define rson mid + 1, r, root << 1 | 1
#define lc root << 1
#define rc root << 1 | 1
#define lowbit(x) ((x) & (-x))

using namespace std;

typedef double db;
typedef long double ldb;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> PI;
typedef pair<ll, ll> PLL;

const db eps = 1e-6;
const int mod = 1e9 + 7;
const int maxn = 4e2 + 100;
const int maxm = 4e5 + 100;
const int inf = 0x3f3f3f3f;
const db pi = acos(-1.0);

int head[maxn], d[maxn];                //
int ver[maxm], edge[maxm], Next[maxm];  // edge[i]: c for edge_i
int n, m, s, t, tot, maxflow;
queue<int> q;
void add(int x, int y, int z) {
    ver[++tot] = y, edge[tot] = z, Next[tot] = head[x], head[x] = tot;

    ver[++tot] = x, edge[tot] = 0, Next[tot] = head[y], head[y] = tot;
}
int du[maxn];
bool bfs() {
    mem(d, 0);
    while (!q.empty()) q.pop();
    q.push(s);
    d[s] = 1;
    while (!q.empty()) {
        int x = q.front();
        q.pop();
        for (int i = head[x]; i; i = Next[i]) {
            if (edge[i] && !d[ver[i]]) {
                q.push(ver[i]);
                d[ver[i]] = d[x] + 1;
                if (ver[i] == t)
                    return true;
            }
        }
    }
    return false;
}
int nx[maxn];
int dinic(int x, int flow) {
    if (x == t)
        return flow;
    int rest = flow, k;
    for (int i = head[x]; i; i = Next[i]) {
        if (edge[i] && d[ver[i]] == d[x] + 1) {
            k = dinic(ver[i], min(rest, edge[i]));
            if (!k) {
                d[ver[i]] = 0;
            } else {
                nx[x] = ver[i];
                edge[i] -= k;
                edge[i ^ 1] += k;
                rest -= k;
            }
        }
    }
    return flow - rest;
}
int vis[maxn];
int pre[maxn];
int main() {
    mem(pre, -1);
    s = 404;
    t = 402;
    tot = 1;
    scanf("%d %d", &n, &m);
    for (int i = 1; i <= m; i++) {
        int x, y;
        scanf("%d %d", &x, &y);
        x *= 2;
        y *= 2;
        add(x, y + 1, 1);
    }
    for (int i = 1; i <= n; i++) {
        add(s, i * 2, 1);
        add(i * 2 + 1, t, 1);
    }
    int maxflow = 0;
    int flow;
    while (bfs()) {
        while (1) {
            flow = dinic(s, inf);
            if (flow == 0)
                break;
            maxflow += flow;
        }
    }
    for (int i = 1; i <= n; i++) {
        pre[(nx[i * 2] - 1) / 2] = i;
    }

    for (int i = 1; i <= n; i++) {
        if (vis[i])
            continue;
        if (pre[i] == -1) {
            int x = i;
            while (x) {
                vis[x] = 1;
                printf("%d ", x);
                x = (nx[x * 2] - 1) / 2;
            }
            printf("\n");
        }
    }
    printf("%d\n", n - maxflow);
    return 0;
}

/*
5 3
1 2 3 4 5
1 2 3
2 1 4
4 3 5
 */

 

posted @ 2019-04-08 16:09  wrjlinkkkkkk  阅读(163)  评论(0编辑  收藏  举报