Gym 101308I Inspection

题意:

用最少的路径,覆盖掉所有的边,(点可以重复);

不是用最小路径覆盖,最小路径覆盖是覆盖点;

分析:

建图:入度<出度,说明这是个起点,从这里出发,入度>出度,说明从这里结束;

先找出一个最大的可行流 f,反着求一遍最大流fmax ,就是最小的可行流了;

输出路径这么变态的东西,我就不会了;这个题目太恶心了;

#include <bits/stdc++.h>

using namespace std;

const int maxn = 100 + 5;
const int inf = 0x3f3f3f3f;

struct Edge {
    int from,to,cap,flow;
};

struct Dinic {
    int n,m,s,t;
    vector<Edge> edges;
    vector<int> G[maxn];
    bool vis[maxn];
    int d[maxn];
    int cur[maxn];

    void init() {
        edges.clear();
        for(int i=0; i<maxn; i++)
            G[i].clear();
    }

    void AddEdge(int from,int to,int cap) {
        edges.push_back((Edge) {
            from,to,cap,0
        });
        edges.push_back((Edge) {
            from,to,0,0
        });
        m = edges.size();
        G[from].push_back(m-2);
        G[to].push_back(m-1);
    }

    bool BFS() {
        memset(vis,0,sizeof(vis));
        queue<int> Q;
        Q.push(s);
        d[s] = 0;
        vis[s] = 1;
        while(!Q.empty()) {
            int x = Q.front();
            Q.pop();
            for(int i=0; i<G[x].size(); i++) {
                Edge& e = edges[G[x][i]];
                if(!vis[e.to]&&e.cap>e.flow) {
                    vis[e.to] = 1;
                    d[e.to] = d[x] + 1;
                    Q.push(e.to);
                }
            }

        }
        return vis[t];
    }

    int DFS(int x,int a) {
        if(x==t||a==0) return a;
        int flow = 0,f;
        for(int& i=cur[x]; i<G[x].size(); i++) {
            Edge& e = edges[G[x][i]];
            if(d[x]+1==d[e.to]&&(f=DFS(e.to,min(a,e.cap-e.flow)))>0) {
                e.flow +=f;
                edges[G[x][i]^1].flow -=f;
                flow+=f;
                a-=f;
                if(a==0) break;
            }
        }
        return flow;
    }

    int Maxflow(int s,int t) {
        this->s = s;
        this->t = t;
        int flow = 0;
        while(BFS()) {
            memset(cur,0,sizeof(cur));
            flow+=DFS(s,inf);
        }
        return flow;
    }

//    int dfs(int u) {
//        if(u==t) return 1;
//        for(int i=0; i<G[u].size(); i++) {
//            Edge& e = edges[G[u][i]^1];
//            if(!e.cap) continue;
//            e.cap--;
//            if(u!=s) putchar(' ');
//            if(e.to!=t) printf("%d",e.to);
//            return dfs(e.to);
//        }
//        return 0;
//    }

} sol;

int d[maxn];
int n;
int ans;

int s,t;


int main() {
    while(scanf("%d",&n)!=EOF) {
        memset(d,0,sizeof(d));
        ans = 0;
        sol.init();
        for(int i=1; i<=n; i++) {
            int k;
            scanf("%d",&k);
            int to;
            for(int j=0; j<k; j++) {
                scanf("%d",&to);
                to;
                d[to]++;
                d[i]--;
                sol.AddEdge(i,to,inf);
            }
        }

        s = 0,t=n+1;
        for(int i=0; i<n; i++) {
            if(d[i]<0) {
                sol.AddEdge(s,i,-d[i]);
                ans-=d[i];
            } else if(d[i]>0)
                sol.AddEdge(i,t,d[i]);
        }

        ans-=sol.Maxflow(t,s);  //反向最大流
        printf("%d
",ans);

    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/TreeDream/p/6973605.html