POJ-1161-Walls
http://poj.org/problem?id=1161
对于空地i,j,若i,j相邻,则G[i][j]=1,即需要翻越一个城墙,否则G[i][j]=0,然后一遍floyd求出一个空地到另一个空地需要翻越的最少城墙数,最后枚举在哪个空地开Party就行了
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define MAX 99999999
#define N 250
int people[N],area[N][N],G[N][N],Dis[N];
int n,m,l;
int Min(int x,int y)
{
return x<y?x:y;
}
void init()
{
int i,j,k1,k2;
scanf("%d%d%d",&m,&n,&l);
for(i=1;i<=l;i++)
{
scanf("%d",&j);
people[j]=i;
}
for(i=1;i<=m;i++)
for(j=1;j<=m;j++)
if(i!=j)
G[i][j]=MAX;
for(i=1;i<=m;i++)
{
scanf("%d",&area[i][0]);
for(j=1;j<=area[i][0];j++)
scanf("%d",&area[i][j]);
area[i][area[i][0]+1]=area[i][1];
for(j=1;j<=area[i][0];j++) //判断两块空地是否相邻(只要有一条边重合)
for(k1=1;k1<i;k1++)
for(k2=1;k2<=area[k1][0];k2++)
if(area[i][j]==area[k1][k2+1]&&area[i][j+1]==area[k1][k2])
G[i][k1]=G[k1][i]=1;
}
}
void floyd()
{
int i,j,k;
for(k=1;k<=m;k++)
for(i=1;i<=m;i++)
for(j=1;j<=m;j++)
G[i][j]=Min(G[i][k]+G[k][j],G[i][j]);
}
void solve()
{
int i,j,k,ans=MAX,best=0,sum;
for(i=1;i<=m;i++) //枚举在哪个空地办Party,Dist数组为每个人到当前枚举空地的最短距离
{
for(j=1;j<=l;j++)
Dis[j]=MAX;
for(j=1;j<=m;j++)
for(k=1;k<=area[j][0];k++)
if(people[area[j][k]]>0&&Dis[people[area[j][k]]]>G[i][j])
Dis[people[area[j][k]]]=G[i][j];
sum=0;
for(j=1;j<=l;j++)
sum+=Dis[j];
if(sum<ans)
{
ans=sum;
best=i;
}
}
printf("%d\n",ans);
}
int main()
{
init();
floyd();
solve();
return 0;
}