您的位置:首页 > 其它

POJ 1161 Walls

2012-08-15 21:19 531 查看
题意: 有 N个村庄,和 M 个区域,M个区域是由N个村庄之间的围墙分割而成,如:



图中10个村庄间的围墙把地形分成了10 个区域,

知道了一些人的所在的村庄的位置,想找一个区域,使得这些人到达这个区域经过的围墙数总和最小,并求出最小值。

分析: 要把各个区域看成点,两两区域间的围墙看成边来建图,如果两块区域之间有围墙相隔,那么就在这两个区域之间建一条长度为1 的边,

图建完之后用 FLOYED 求出两两点的最短距离,

计算每个人到达某个区域的最小距离时,要枚举和该人所在村庄相邻的区域。

依次枚举目标区域找出最小值。

#include<stdio.h>
#include<string.h>
#define INF 0x1f1f1f1f
#define clr(x)memset(x,0,sizeof(x))
struct node
{
int to,next;
}e[2000000];
int tot;
int head[303];
void add(int s,int u)
{
e[tot].to=u;
e[tot].next=head[s];
head[s]=tot++;
}
int g[255][255];
int t[255][255];
int a[255];
int v[303];
int p[303];
int main()
{
int pn,m,i,n,j,k,c,sum,tmp,tt;
while(scanf("%d%d",&m,&n)!=EOF)
{
tot=1;
clr(head);
clr(v);
clr(t);
memset(g,-1,sizeof(g));
scanf("%d",&pn);
for(i=1;i<=m;i++)
g[i][i]=0;
for(i=1;i<=pn;i++)
{
scanf("%d",&p[i]);
v[p[i]]=i;
}
for(i=1;i<=m;i++)
{
scanf("%d",&k);
for(j=0;j<k;j++)
{
scanf("%d",&a[j]);
if(v[a[j]])
add(p[v[a[j]]],i);
}
for(j=0;j<k;j++)
{
c=t[a[j]][a[(j+1)%k]];
if(c)
g[i][c]=g[c][i]=1;
else
t[a[j]][a[(j+1)%k]]=t[a[(j+1)%k]][a[j]]=i;
}
}
for(k=1;k<=m;k++)
for(i=1;i<=m;i++)
if(g[i][k]!=-1)
for(j=1;j<=m;j++)
if(g[k][j]!=-1&&(g[i][k]+g[k][j]<g[i][j]||g[i][j]==-1))
g[i][j]=g[i][k]+g[k][j];
sum=INF;
for(i=1;i<=m;i++)
{
tt=0;
for(j=1;j<=pn;j++)
{
tmp=INF;
for(k=head[p[j]];k;k=e[k].next)
{
if(g[e[k].to][i]<tmp)
tmp=g[e[k].to][i];
}
tt+=tmp;
}
if(tt<sum)
sum=tt;
}
printf("%d\n",sum);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: