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; }