poj1161Walls

View Code
/*poj1161Walls
1.求与城市连接的区域,即环绕城市,能从城市直接到达的区域:若区域i的边界点里包含城市A,则A与
区域i是连接的。
2.求与区域连接的区域(这是主要的难点):因为区域的边界是按照顺时针排列的,假如说区域i边界点有
a, b,这说明边界a-b是与区域i是相邻的,这时如果区域j的边界点有b, a(注意不是a, b,因为在区域i是顺时针,那么
在区域j就是逆时针了),这说明边界b-a是与区域j是相邻的,于是i与j就相邻了。注意一条边只能与两个区域相邻
*/
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
#define INF 10000000
#define MAXN 555
int m,n,l,a,b,c,mem[MAXN],d[MAXN][MAXN],g[MAXN][MAXN],map[MAXN][MAXN];
//mem[]记录成员所在的城市,d[a][b]区域a到区域b需要经过wall的数量,g[a][b]边a-b相邻的
//域,map[a][b]城市a和区域b的连通性,城市的编号从到n,区域的编号从+n到m+n
void init()
{
memset(mem,0,sizeof(mem));
for(int i=1;i<=m+n;i++)
for(int j=1;j<=m+n;j++)
d[i][j]=(i==j?0:INF);
memset(g,0,sizeof(g));
}
void preprocess()
{
for(int i=1;i<=l;i++)
{
scanf("%d",&mem[i]);
}
int first;
for(int i=1+n;i<=m+n;i++)//区域编号
{
scanf("%d",&c);
for(int j=1;j<=c;j++)
{
scanf("%d",&b);
map[b][i]=1;//城市b与区域i相邻
if(j==1){first=b;a=b;continue;}
g[a][b]=i;//边a-b与区域i相邻
a=b;
}
g[b][first]=i;
}
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
if(!g[i][j])continue;
int u=g[i][j],v=g[j][i];
d[u][v]=1;//区域u与区域v相邻,隔一道墙
}
}
void floyed()
{
for(int k=1+n;k<=n+m;k++)
for(int i=1+n;i<=m+n;i++)
for(int j=1+n;j<=m+n;j++)
if(d[i][j]>d[i][k]+d[k][j])
d[i][j]=d[i][k]+d[k][j];
}
int ans;
void wall()
{
int sum,tmp;
ans=INF;
for(int i=1+n;i<=m+n;i++)
{
sum=0;
for(int j=1;j<=l;j++)
{
int x=mem[j];
tmp=INF;
for(int k=1+n;k<=n+m;k++)
{
if(map[x][k])
{
tmp=min(tmp,d[k][i]);
}
}
sum+=tmp;
}
ans=min(sum,ans);
}
}
int main()
{
scanf("%d%d%d",&m,&n,&l);
init();
preprocess();
floyed();
wall();
printf("%d\n",ans);
}

原文地址:https://www.cnblogs.com/sook/p/2226441.html