poj 1161
自己总算真正独立的做了一道题,我的思路是这样的:将每一个区域抽象成一个节点,结果就是每个club成员到某一点的最小距离之和。关键就是构图了,每一块相邻的区域,就是直连的两节点,也就是说原图中的每一条边有且仅关联两个区域。在构造图的过程中需要保留club的每个成员可以出发的区域。重新构造图之后对每个顶点进行一次广搜找出最小值就行了。代码如下:
#include<iostream>
#include<queue>
#include<vector>
#include<cstring>
using namespace std;
#define MAX_INT 1234567890
struct node
{
int i;
int floor;
};
int edge[255][255],member[255],visit[255],floor[255];
vector <int> map[255];
vector <int> start[255];
int bfs(int s)
{
int j,k;
queue <node> Q;
node e={s,0};
Q.push(e);floor[e.i]=0;
visit[e.i]=1;
while(!Q.empty())
{
e=Q.front();
Q.pop();
k=e.i;
for(j=0;j<map[k].size();j++)
{
node e1={map[k][j],e.floor+1};
if(!visit[e1.i])
{
Q.push(e1);
visit[e1.i]=1;
floor[e1.i]=e1.floor;
}
}
}
return 0;
}
int main()
{
int i,j,k,s,nCity,nRegin,num,sum,min,min1,cur,pre,first;
while(cin>>nRegin>>nCity)
{
cin>>num;
for(i=0;i<num;i++)
cin>>member[i];
memset(edge,0,sizeof(edge));
memset(visit,0,sizeof(visit));
//构图
for(i=1;i<=nRegin;i++)
{
cin>>s>>pre;
first=pre;
start[pre].push_back(i);//保留每个顶点可以出发的区域
for(j=1;j<s;j++)
{
cin>>cur;
start[cur].push_back(i);
//确定相邻节点
if(!edge[pre][cur])
{
edge[pre][cur]=i;
edge[cur][pre]=i;
}
else
{
map[edge[pre][cur]].push_back(i);
map[i].push_back(edge[pre][cur]);
}
pre=cur;
}
if(!edge[cur][first])
{
edge[cur][first]=i;
edge[first][cur]=i;
}
else
{
map[edge[cur][first]].push_back(i);
map[i].push_back(edge[cur][first]);
}
}
//对每个顶点开始进行广搜
min1=MAX_INT;
for(i=1;i<=nRegin;i++)
{
memset(floor,0,sizeof(floor));
memset(visit,0,sizeof(visit));
bfs(i);
sum=0;
for(j=0;j<num;j++)
{
s=member[j];min=MAX_INT;
for(k=0;k<start[s].size();k++)
{
//确定每个成员从可与出发的区域到目的区域的最短距离
if(min>floor[start[s][k]]) min=floor[start[s][k]];
}
sum+=min;
}
if(min1>sum) min1=sum;
}
cout<<min1<<endl;
for(i=0;i<=nRegin;i++)
map[i].clear();
for(i=1;i<=nCity;i++)
start[i].clear();
}
return 0;
}
浙公网安备 33010602011771号