HDU 3488 — Tour 费用流/KM算法

来源:互联网 发布:ubuntu yum 编辑:程序博客网 时间:2024/05/16 06:49

原题:http://acm.hdu.edu.cn/showproblem.php?pid=3488

题意:

有n个点,m条有向带权边;

求一些环,使得每个点属于且仅属于一个环;

问环边的权值和的最小值;


思路:

拆点,建图,跑一个费用流;

源点到节点,流量为1,花费为0(s, i, 0, 1);

节点到节点,流量为1, 花费为边权值(u, v+n, cos, 1);

节点到汇点,流量为1,花费为0(i+n, t, 0, 1);




#include <cstdio>#include <cstring>#include <queue>#include <vector>#define oo 0x3f3f3f3f#define maxn 410using namespace std;struct Edge {    int u, v, c, f;    Edge( int u, int v, int c, int f ):u(u),v(v),c(c),f(f){}};struct Mcmf {    int n, src, dst;    vector<Edge> edge;    vector<int> g[maxn];    int dis[maxn], ext[maxn], pth[maxn];    void init( int nn, int s, int d ){        n = nn;        src = s;        dst = d;        for( int i=1; i<=n; i++ )            g[i].clear();        edge.clear();    }    void add_edge( int u, int v, int c, int f ){        g[u].push_back( edge.size() );        edge.push_back( Edge(u,v,c,f) );        g[v].push_back( edge.size() );        edge.push_back( Edge(v,u,-c,0) );    }    bool spfa( int &flow, int &cost ) {        queue<int> qu;        memset( dis, 0x3f, sizeof(dis) );        qu.push( src );        dis[src] = 0;        ext[src] = true;        pth[src] = -1;        while( !qu.empty() ) {            int u = qu.front();            qu.pop();            ext[u] = false;            for( int t=0; t<g[u].size(); t++) {                Edge &e = edge[g[u][t]];                if( e.f && dis[e.v]>dis[e.u]+e.c ) {                    dis[e.v] = dis[e.u]+e.c;                    pth[e.v] = g[u][t];                    if( !ext[e.v] ) {                        ext[e.v] = true;                        qu.push( e.v );                    }                }            }        }        if( dis[dst]==oo ) return false;        int flw = oo;        for( int eid=pth[dst]; eid!=-1; eid=pth[edge[eid].u] )             flw = min( flw, edge[eid].f );        for( int eid=pth[dst]; eid!=-1; eid=pth[edge[eid].u] ) {            edge[eid].f -= flw;            edge[eid^1].f += flw;        }        flow += flw;        cost += flw*dis[dst];        return true;    }    void mcmf( int &flow, int &cost ) {        flow = cost = 0;        while( spfa(flow,cost) );    }};int n, m;Mcmf M;int main() {    int cas;    scanf( "%d", &cas);    while(cas--) {        scanf( "%d%d", &n, &m);        int s = 0, t = n*2+1;        M.init(t+1, s, t);        for(int i = 1;i<=m;i++) {int u, v, cos;            scanf("%d%d%d", &u, &v, &cos);            M.add_edge(u, v+n, cos, 1);        }        for(int i = 1;i<=n;i++) {            M.add_edge(M.src, i, 0, 1);            M.add_edge(i+n, M.dst, 0, 1);        }        int flow, cost;        M.mcmf(flow, cost);        printf("%d\n", cost);    }    return 0;}


0 0
原创粉丝点击