Q - Tour - hdu 3488(最小匹配值)

题意:一个王国有N个城市,M条路,都是有向的,现在可以去旅游,不过走的路只能是环(至少也需要有两个城市),他们保证这些城市之间的路径都是有环构成的,现在至少需要走多少路。
分析:因为是有向图所以,而且走的是环所以每个城市都会进入一次并且出去一次,构成二分图,并且是完备匹配(完备匹配后肯定都是环了),现在只需要求出来这些匹配的最小值就行,可以把路径的值变为负数,然后求最大匹配值,最后的结果在变成相反数即可,注意路径可能有多条,输入的时候注意取最小的那个
*************************************************************************

 

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;

const int MAXN = 205;
const int oo = 1e9+7;

int g[MAXN][MAXN], slack[MAXN], N;
int dx[MAXN], dy[MAXN], Ly[MAXN];
bool vx[MAXN], vy[MAXN];

void InIt()
{
    memset(Ly, falsesizeof(Ly));
    memset(dy, falsesizeof(dy));

    for(int i=1; i<=N; i++)
    {
        dx[i] = -oo;
        for(int j=1; j<=N; j++)
            g[i][j] = -oo;
    }
}
bool Find(int i)
{
    vx[i] = true;
    for(int j=1; j<=N; j++)
    {
        if(!vy[j] && dx[i]+dy[j] == g[i][j])
        {
            vy[j] = true;

            if(!Ly[j] || Find(Ly[j]))
            {
                Ly[j] = i;
                return true;
            }
        }
        else if(!vy[j])
            slack[j] = min(slack[j], dx[i]+dy[j]-g[i][j]);
    }

    return false;
}
int KM()
{
    int i, j;

    for(i=1; i<=N; i++)
    {
        for(j=1; j<=N; j++)
            slack[j] = oo;
        while(true)
        {
            memset(vx, falsesizeof(vx));
            memset(vy, falsesizeof(vy));

            if( Find(i) == true )break;

            int d = oo;

            for(j=1; j<=N; j++)
            {
                if(!vy[j] && d > slack[j])
                    d = slack[j];
            }

            for(j=1; j<=N; j++)
            {
                if(vx[j])dx[j] -= d;
                if(vy[j])dy[j] += d;
            }
        }
    }

    int sum = 0;

    for(i=1; i<=N; i++)
        sum += g[Ly[i]][i];

    return -sum;
}

int main()
{
    int T;

    scanf("%d", &T);

    while(T--)
    {
        int M, u, v, w;

        scanf("%d%d", &N, &M);
        InIt();

        while(M--)
        {
            scanf("%d%d%d", &u, &v, &w);
            g[u][v] = max(g[u][v], -w);
            dx[u] = max(dx[u], g[u][v]);
        }

        printf("%d\n", KM());
    }

    return 0;
}

 

posted @ 2015-08-06 09:10  无忧望月  阅读(211)  评论(0编辑  收藏  举报
levels of contents