UVA-1349 - Optimal Bus Route Design(KM最佳完美匹配)

题意:有n个景点,每个景点之间有一些带权有向边,要求你设计一些线路,要求线路是一个圈,并且每个景点只能有一条线路经过,并且只能经过一次(起始点除外),问你,若存在,求这些线路权值的最小和,否则输出"N"

分析:这题和上一题HDU差不多,只是这题有可能不存在解决方案.同样这题也有重边

若不存在解决方案,则对于有些点,不存在Left[i]和i的边,故w[Left[i]][i]=-INF;

http://www.cnblogs.com/arbitrary/archive/2013/04/21/3034424.html

// File Name: 1349.cpp
// Author: Zlbing
// Created Time: 2013/4/21 20:48:33

#include<iostream>
#include<string>
#include<algorithm>
#include<cstdlib>
#include<cstdio>
#include<set>
#include<map>
#include<vector>
#include<cstring>
#include<stack>
#include<cmath>
#include<queue>
using namespace std;
#define CL(x,v); memset(x,v,sizeof(x));
#define INF 0x3f3f3f3f
#define LL long long
#define REP(i,r,n) for(int i=r;i<=n;i++)
#define RREP(i,n,r) for(int i=n;i>=r;i--)
const int MAXN=105;
int Left[MAXN];
int w[MAXN][MAXN];
int Lx[MAXN],Ly[MAXN];
bool S[MAXN],T[MAXN];
int N;
bool match(int i)
{
    S[i]=true;
    for(int j=1;j<=N;j++)if(Lx[i]+Ly[j]==w[i][j]&&!T[j])
    {
        T[j]=true;
        if(Left[j]==0||match(Left[j]))
        {
            Left[j]=i;
            return true;
        }
    }
    return false;
}
void update(){
    int a=INF;
    for(int i=1;i<=N;i++)if(S[i])
        for(int j=1;j<=N;j++)if(!T[j])
            a=min(a,Lx[i]+Ly[j]-w[i][j]);
    for(int i=1;i<=N;i++){
        if(S[i])Lx[i]-=a;
        if(T[i])Ly[i]+=a;
    }
}
void KM()
{
    for(int i=1;i<=N;i++){
        Left[i]=Lx[i]=Ly[i]=0;
        for(int j=1;j<=N;j++)
        {
            Lx[i]=max(Lx[i],w[i][j]);
        }
    }
    for(int i=1;i<=N;i++){
        for(;;){
            CL(S,0);
            CL(T,0);
            if(match(i))break;
            else update();
        }
    }
}
int main()
{
    while(~scanf("%d",&N))
    {
        if(!N)break;
        REP(i,0,N)
            REP(j,0,N)
            w[i][j]=-INF;
        REP(i,1,N)
        {
            while(true){
                int a,b;
                scanf("%d",&a);
                if(!a)break;
                scanf("%d",&b);
                w[i][a]=max(w[i][a],-b);
            }
        }
        KM();
        bool flag=true;
        REP(i,1,N)if(w[Left[i]][i]==-INF)flag=false;
//        REP(i,1,N)
//        {
//            REP(j,1,N)
//                printf("w[%d][%d]=%d ",i,j,w[i][j]);
//            printf("\n");
//        }
//        REP(i,1,N)printf("Left%d\n",Left[i]);
        int ans=0;
        if(flag)
        {
            REP(i,1,N)
                ans+=-w[Left[i]][i];
            printf("%d\n",ans);
        }
        else printf("N\n");
    }
    return 0;
}

 

posted @ 2013-04-21 21:37  z.arbitrary  阅读(413)  评论(0编辑  收藏  举报