zoukankan      html  css  js  c++  java
  • UVA 1349(二分图匹配)

    1349 - Optimal Bus Route Design

    Time limit: 3.000 seconds

    A big city wants to improve its bus transportation system. One of the improvement is to add scenic routes which go es through attractive places. Your task is to construct a bus-route-plan for sight-seeing buses in a city.

    You are given a set of scenic lo cations. For each of these given lo cations, there should be only one bus route that passes this lo cation, and that bus route should pass this lo cation exactly once. The number of bus routes is unlimited. However, each route should contain at least two scenic lo cations.

    From location i to location j , there may or may not be a connecting street. If there is a street from location i to location j , then we say j is an out-neighbor of i . The length of the street from i to j is d (i, j) . The streets might be one way. So it may happen that there is a street from i to j , but no street from j to i . In case there is a street from i to j and also a street from j to i , the lengths d (i, j) and d (j, i) might be different. The route of each bus must follow the connecting streets and must be a cycle. For example, the route of Bus A might be from location 1 to location 2, from location 2 to location 3, and then from location 3 to location 1. The route of Bus B might be from location 4 to location 5, then from location 5 to location 4. The length of a bus route is the sum of the lengths of the streets in this bus route. The total length of the bus-route-plan is the sum of the lengths of all the bus routes used in the plan. A bus-route-plan is optimal if it has the minimum total length. You are required to compute the total length of an optimal bus-route-plan.

    Input 

    The input file consists of a number of test cases. The first line of each test case is a positive integer n , which is the number of locations. These n locations are denoted by positive integers 1, 2,..., n . The next n lines are information about connecting streets between these lo cations. The i -th line of these n lines consists of an even number of positive integers and a 0 at the end. The first integer is a lo cation j which is an out-neighbor of location i , and the second integer is d (i, j) . The third integer is another location j' which is an out-neighbor of i , and the fourth integer is d (i, j') , and so on. In general, the (2k - 1) th integer is a location t which is an out-neighbor of location i , and the 2k th integer is d (i, t) .

    The next case starts immediately after these n lines. A line consisting of a single `0' indicates the end of the input file.

    Each test case has at most 99 locations. The length of each street is a positive integer less than 100.

    Output 

    The output contains one line for each test case. If the required bus-route-plan exists, then the output is a positive number, which is the total length of an optimal bus-route-plan. Otherwise, the output is a letter `N'.

    Sample Input 

    3 
    2 2 3 1 0 
    1 1 3 2 0 
    1 3 2 7 0  
    8 
    2 3 3 1 0 
    3 3 1 1 4 4 0
    1 2 2 7 0 
    5 4 6 7 0 
    4 4 3 9 0 
    7 4 8 5 0 
    6 2 5 8 8 1 0
    6 6 7 2 0
    3 
    2 1 0 
    3 1 0 
    2 1 0
    0
    

    Sample Output 

    7 
    25 
    N
    


    题意:有n个景点,每个景点之间有一些带权有向边,要求你设计一些线路,要求线路是一个圈,并且每个景点只能有一条线路经过,并且只能经过一次(起始点除外),问你,若存在,求这些线路权值的最小和,否则输出"N"
    法一:
    KM
    #include <cstdio>
    #include <iostream>
    #include <sstream>
    #include <cmath>
    #include <cstring>
    #include <cstdlib>
    #include <string>
    #include <vector>
    #include <map>
    #include <set>
    #include <queue>
    #include <stack>
    #include <algorithm>
    using namespace std;
    #define ll long long
    #define _cle(m, a) memset(m, a, sizeof(m))
    #define repu(i, a, b) for(int i = a; i < b; i++)
    #define repd(i, a, b) for(int i = b; i >= a; i--)
    #define sfi(n) scanf("%d", &n)
    #define pfi(n) printf("%d
    ", n)
    #define sfi2(n, m) scanf("%d%d", &n, &m)
    #define pfi2(n, m) printf("%d %d
    ", n, m)
    #define pfi3(a, b, c) printf("%d %d %d
    ", a, b, c)
    #define MAXN 105
    #define V 55
    
    /*  KM算法
     *   复杂度O(nx*nx*ny)
     *  求最大权匹配
     *   若求最小权匹配,可将权值取相反数,结果取相反数
     *  点的编号从0开始
     */
    const int N = 310;
    const int INF = 0x3f3f3f3f;
    int nx,ny;//两边的点数
    int g[N][N];//二分图描述
    int linker[N],lx[N],ly[N];//y中各点匹配状态,x,y中的点标号
    int slack[N];
    bool visx[N],visy[N];
    
    bool DFS(int x)
    {
        visx[x] = true;
        for(int y = 0; y < ny; y++)
        {
            if(visy[y])continue;
            int tmp = lx[x] + ly[y] - g[x][y];
            if(tmp == 0)
            {
                visy[y] = true;
                if(linker[y] == -1 || DFS(linker[y]))
                {
                    linker[y] = x;
                    return true;
                }
            }
            else if(slack[y] > tmp)
                slack[y] = tmp;
        }
        return false;
    }
    void KM()
    {
        memset(linker,-1,sizeof(linker));
        memset(ly,0,sizeof(ly));
        for(int i = 0;i < nx;i++)
        {
            lx[i] = -INF;
            for(int j = 0;j < ny;j++)
                if(g[i][j] > lx[i])
                    lx[i] = g[i][j];
        }
        for(int x = 0;x < nx;x++)
        {
            for(int i = 0;i < ny;i++)
                slack[i] = INF;
            while(true)
            {
                memset(visx,false,sizeof(visx));
                memset(visy,false,sizeof(visy));
                if(DFS(x))break;
                int d = INF;
                for(int i = 0;i < ny;i++)
                    if(!visy[i] && d > slack[i])
                        d = slack[i];
                for(int i = 0;i < nx;i++)
                    if(visx[i])
                        lx[i] -= d;
                for(int i = 0;i < ny;i++)
                {
                    if(visy[i])ly[i] += d;
                    else slack[i] -= d;
                }
            }
        }
    
        //return res;
    }
    //HDU 2255
    int main()
    {
        int n;
        while(scanf("%d",&n) && n)
        {
            int tn = 2 * n;
            int x, y, c;
            repu(i, 0, n) repu(j, 0, n) g[i][j] = -INF;
            for(int i = 0;i < n;i++)
            {
                while(1)
                {
                    sfi(y);
                    if(y == 0) break;
                    y--;
                    sfi(c);
                    g[i][y] = max(-c, g[i][y]);
                }
            }
            nx = ny = n;
            KM();
    
            int res = 0, flag = 0;
            for(int i = 0;i < ny;i++)
            {
                 if(g[linker[i]][i] == -INF) {flag = 1; break;}
                 res += g[linker[i]][i];
            }
            if(flag)
            printf("N
    ");
            else printf("%d
    ", -res);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    《Mysql
    《Redis
    《pt-query-digest 剖析 Mysql 慢日志》
    《Redis
    《Redis
    《Redis
    《Redis
    《Redis
    python中__new__()与__init__()的区别
    Python常见综合面试题
  • 原文地址:https://www.cnblogs.com/sunus/p/4836599.html
Copyright © 2011-2022 走看看