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;

}

你可能感兴趣的:(poj)