您的位置:首页 > 其它

poj1161 walls floyd算法+把面当结点建图

2015-11-09 10:49 796 查看
题意:在一个国家里

所有的城镇被城墙分割

因此国家被分为几个区域

从一个区域到另一个区域必须通过城镇或者穿过城墙

每两个城市之间最多只有一个城墙

这里有一个俱乐部,俱乐部的人住在城镇里

这个城镇最多只有一个人

成员们打算在某个区域里开会

他们不想进入城市

并且他们想爱你个尽量少的穿越城墙

为了开会,每个成员都要穿越一定数量的城墙

他们想要每个人穿越城墙数之和最小

城市被标记为1到n

计算出最有区域和最小交叉和

M个区域 2 200

n歌城市  3 250

l成员数 1 30

每个成员居住的城市

思路:把区域当成结点,当两个区域有公共边的时候,那么久说明这两个区域相邻,既有边。如此建图后跑一次floyd就可以知道任意两个结点的最短路了,然后枚举每个聚会区域,再枚举每个俱乐部点的相邻区域,求每个俱乐部点到聚会区域的最少翻墙数,求得sum,并和ans取min就是ans了。

#include<stdio.h>
#include<string.h>
#include <iostream>
using namespace std;
#define maxn 330
int edge[maxn][maxn];
int markedge[maxn][maxn];
int mapi[maxn][maxn];
int secondv,n,m,clubsum,firstv,sum;
int club[maxn];
#define inf INT_MAX
void floyd()
{
for(int i=0; i<m; i++)
mapi[i][i]=0;
for(int k=0; k<m; k++)
{
for(int i=0; i<m; i++)
{
if(mapi[i][k]!=-1)
{
for(int j=0; j<m; j++)
{
if(mapi[k][j]!=-1)
{
if(mapi[i][j]==-1||mapi[i][j]>mapi[i][k]+mapi[j][k])
{
mapi[i][j]=mapi[i][k]+mapi[k][j];
}
}
}
}
}
}
}
int main()
{
while(~scanf("%d",&m))
{
int tmpv,tmpedge;
scanf("%d%d",&n,&clubsum);
for(int i=0; i<clubsum; i++)
scanf("%d",&club[i]);
memset(mapi,-1,sizeof(mapi));
memset(markedge,0,sizeof(markedge));
memset(edge,-1,sizeof(edge));
for(int i=0; i<m; i++)
{
scanf("%d%d",&sum,&firstv);
markedge[firstv][i]=1;
tmpv=firstv;
for(int j=1; j<sum; j++)
{
scanf("%d",&secondv);
markedge[secondv][i]=1;
tmpedge=edge[tmpv][secondv];
if(tmpedge!=-1)
{
mapi[tmpedge][i]=mapi[i][tmpedge]=1;
}
else
{
edge[tmpv][secondv]=edge[secondv][tmpv]=i;
}
tmpv=secondv;
}
tmpedge=edge[tmpv][firstv];
if(tmpedge!=-1)
{
mapi[tmpedge][i]=mapi[i][tmpedge]=1;
}
else
{
edge[tmpv][firstv]=edge[firstv][tmpv]=i;
}
}
floyd();
int ans=inf;
for(int i=0; i<m; i++)
{
int sum=0;
for(int j=0; j<clubsum; j++)
{
int mm=inf;
for(int k=0; k<m; k++)
{
if(markedge[club[j]][k])
{
mm=min(mm,mapi[k][i]);
}
}
sum+=mm;
}
ans=min(ans,sum);
}
printf("%d\n",ans);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: