zoukankan      html  css  js  c++  java
  • Q

    题意:一个王国有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 ", KM());
        }

        return 0;
    }
  • 相关阅读:
    Debian vim没有颜色的解决办法
    第四次作业
    第三次作业
    第二次作业
    Mad Libs游戏 & 华氏温度与摄氏温度转换
    有趣故事
    Mybatis的使用及增删改查
    jdbc数据连接池
    详解MySQL数据类型
    SQL语法大全
  • 原文地址:https://www.cnblogs.com/liuxin13/p/4707044.html
Copyright © 2011-2022 走看看