【第二次周赛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]