第二次周赛D题 hdu 2448 【最短路径+最佳匹配】

【第二次周赛D题】

 

【原题链接】

http://acm.hdu.edu.cn/showproblem.php?pid=2448

【题目大意】

输入一幅图,图中海上若干油井,岸边有若干港口,可以航行的油井之间有相互距离,港口和油井之间有相互距离(港口数小于油井数),有几艘轮船,每个在一个油井(轮船数等于港口数),问所有轮船到港口的所需走的距离和最小是多少?

【解题思想】

先用dij算法找到所有港口到有船油井的最短距离,再通过最佳匹配,找到和值最小的有船油井和港口的搭配。

【注意】

输入量大,需要用scanf输入!

 

[code]

#include <iostream>

#include <cstdio>

#define MAXN 310

#define inf 1000000000

#define _clr(x) memset(x,0xff,sizeof(long)*n)

using namespace std;

 

void dijkstra(long n,long mat[][MAXN],long s,long* MIN){

    long v[MAXN],i,j,k;

    for (i=0;i<n;i++)

        MIN[i]=inf,v[i]=0;

    for (MIN[s]=0,j=0;j<n;j++){

        for (k=-1,i=0;i<n;i++)

            if (!v[i]&&(k==-1||MIN[i]<MIN[k]))

                k=i;

        for (v[k]=1,i=0;i<n;i++)

            if (!v[i]&&MIN[k]+mat[k][i]<MIN[i])

                MIN[i]=MIN[k]+mat[k][i];

    }

}

 

long kuhn_munkras(long m,long n,long mat[][MAXN],long* match1,long* match2){

    long s[MAXN],t[MAXN],l1[MAXN],l2[MAXN],p,q,ret=0,i,j,k;

    for (i=0;i<m;i++)

        for (l1[i]=-inf,j=0;j<n;j++)

            l1[i]=mat[i][j]>l1[i]?mat[i][j]:l1[i];

    for (i=0;i<n;l2[i++]=0);

    for (_clr(match1),_clr(match2),i=0;i<m;i++){

        for (_clr(t),s[p=q=0]=i;p<=q&&match1[i]<0;p++)

            for (k=s[p],j=0;j<n&&match1[i]<0;j++)

                if (l1[k]+l2[j]==mat[k][j]&&t[j]<0){

                    s[++q]=match2[j],t[j]=k;

                    if (s[q]<0)

                        for (p=j;p>=0;j=p)

                            match2[j]=k=t[j],p=match1[k],match1[k]=j;

                }

        if (match1[i]<0){

            for (i--,p=inf,k=0;k<=q;k++)

                for (j=0;j<n;j++)

                    if (t[j]<0&&l1[s[k]]+l2[j]-mat[s[k]][j]<p)

                        p=l1[s[k]]+l2[j]-mat[s[k]][j];

            for (j=0;j<n;l2[j]+=t[j]<0?0:p,j++);

            for (k=0;k<=q;l1[s[k++]]-=p);

        }

    }

    for (i=0;i<m;i++)

        ret+=mat[i][match1[i]];

    return ret;

}

 

long sMap[310][310],map[310][310],partMap[310][310],MIN[310],match1[310],match2[310],in[310];;

 

int main()

{

    long n,m,k,p,i,j,inStation,from,to,d;

    while(scanf("%ld%ld%ld%ld",&n,&m,&k,&p)!=EOF)

    {

        for(i=0;i<n;i++)

        {

            scanf("%ld",&inStation);

            in[i]=inStation;

        }

        for(i=0;i<=m;i++)

            for(j=0;j<=m;j++) sMap[i][j]=inf;

        for(i=0;i<k;i++)

        {

            scanf("%ld%ld%ld",&from,&to,&d);

            sMap[from][to]=d;

            sMap[to][from]=d;

        }

        for(i=0;i<n+m;i++)

            for(j=0;j<n+m;j++)

            {

                map[i][j]=inf;

                partMap[i][j]=inf;

            }

        for(i=0;i<p;i++)

        {

            scanf("%ld%ld%ld",&from,&to,&d);

            to+=n;

            map[from][to]=d;

            map[to][from]=d;

        }

        for(i=0;i<n;i++)

        {

            for(j=0;j<=m;j++)

            {

                sMap[0][j]=map[i+1][j+n];

                sMap[j][0]=map[i+1][j+n];

            }

            dijkstra(m+1,sMap,0,MIN);

            for(j=0;j<n;j++)

            {

                partMap[i][j]=-MIN[in[j]];

            }

        }

        cout<<-kuhn_munkras(n,n,partMap,match1,match2)<<endl;

    }

    return 0;

}

[\code]

你可能感兴趣的:(最短路径)