poj 1161 暴搜(权值都为1的最短路,开会选址)

来源:互联网 发布:网络写手 签约 编辑:程序博客网 时间:2024/05/16 13:57
题意:给出n个点和l个区域(这些区域就是图中的面)。输入前三行为r,n,l,分别表示区域数、点数、和俱乐部数。第四行有l个数,分别标记哪些个点是俱乐部。接下来2*r行,代表r个区域,每个区域由两行表示,第一行为区域由num个点围成的,第二行num个数代表是哪些点围成这个区域,这些点按顺时针(最后一个表示最外区域时是逆时针)围成这个区域,相邻两点代表一条边。问,在图中找出一个区域,使得所有俱乐部点到这个区域所要穿过的边之和最少,输出最少的边数之和。

思路:实际上就是暴搜。先以面之间是否直连构图(注意flag的应用)。然后枚举每个club点,算其与所有面的最短距离,实际上就是权值都为1的最短路,bfs即可(必须穿过的边数)。最后扫一遍r个区域求最小值即可。这样做的复杂度是O(nr)。(其他人有的做法是通过上面构图求Floyd最短路,然后再找没有必要)。

#include <cstdio>#include <cstring>#include <algorithm>using namespace std;#define N 255#define R 205int c[35],g[R][R],flag[N][N],dis[35][R],adj[N][R],used[R];int r,n,l;void bfs(int j){    int i,now,front,rear,q[N],x;    x = c[j];    front = rear = -1;    memset(used, 0, sizeof(used));    for(i = 1;i<=r;i++)        if(adj[x][i]){            dis[j][i] = 0;            used[i] = 1;            q[++rear] = i;        }    while(front < rear){        now = q[++front];        for(i = 1;i<=r;i++)            if(g[now][i] && !used[i]){                used[i] = 1;                q[++rear] = i;                dis[j][i] = dis[j][now]+1;            }    }}int main(){    int i,j,num,a,b=0,tmp,res=0x3fffffff;    memset(flag, 0, sizeof(flag));    memset(dis, 0, sizeof(dis));    memset(adj, 0, sizeof(adj));    memset(g, 0, sizeof(g));    scanf("%d %d %d",&r,&n,&l);    for(i = 1;i<=l;i++)        scanf("%d",&c[i]);    for(i = 1;i<=r;i++){        scanf("%d",&num);        scanf("%d",&a);        adj[a][i] = 1;        tmp = a;        for(j = 1;j<num;j++){            scanf("%d",&b);            adj[b][i] = 1;            if(!flag[a][b])                flag[a][b] = flag[b][a] = i;            else                g[i][flag[a][b]] = g[flag[a][b]][i] = 1;            a = b;        }        if(num>=3){            if(!flag[tmp][b])                flag[tmp][b] = flag[b][tmp] = i;            else                g[i][flag[tmp][b]] = g[flag[tmp][b]][i] = 1;        }    }    for(i = 1;i<=l;i++)        bfs(i);    for(i = 1;i<=r;i++){        for(j = 1,tmp = 0;j<=l;j++)            tmp += dis[j][i];        res = min(res,tmp);    }    printf("%d\n",res);    return 0;}


0 0
原创粉丝点击