poj 1161 Floyd+枚举

题意是:

给出n个点,围成m个区域。从区域到另一个区域间需穿过至少一条边(若两区域相邻)——边连接着两点。

给出这么一幅图,并给出一些点,问从这些点到同一个区域的穿过边数最小值。

解题思路如下:

将区域按1~m编号,d[i][j]表示第 i 个区域到第 j 个区域的最短距离,跑一遍Floye算法O(m^3)后,枚举选择的区域,找出其中穿过边数最小值即可。

建图:题目对于每个区域的描述方式为以顺时针方向给出围成区域的点。由此可知区域由哪些边组成。易知,每条边能且只能令两个区域相邻,则用二维数组记录当前边结点所围成的区域编号,如vis[i][j]表示结点 i 和结点 j 的之间的边参与围成的区域编号。开始时memset(vis ,0,sizeof(vis)); 若是0,则将其赋值为区域编号;否则得到了相邻区域的编号,赋值d[i][vis[u][v]]=1,则初始化完成。

注意给vis数组赋值时需要vis[i][j]=vis[j][i]=区域编号。

枚举时,因为是计算从某些点到同一区域的最小距离和,而d[][]记录的是区域与区域之间的和,因此以下两点:

1. 对d[i][i]必须赋值为0,这题会用到

2. 为了方便枚举,用belong数组来记录所有点所属的区域。因此求该点到某一区域的最小距离转化成了求该点所有所属区域中到某一区域的最小距离,直接d[i][j]即可。

代码如下

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<vector>
 6 using namespace std;
 7 #define inf 1<<29
 8 int n,m,l,num,town,d[305][305],club[35],vis[305][305];
 9 vector<int> region[205],belong[305];
10 void Floyd(){
11     for(int k=1;k<=m;k++)
12         for(int i=1;i<=m;i++)
13             for(int j=1;j<=m;j++) if(i!=j)
14                 d[i][j]=min(d[i][j],d[i][k]+d[k][j]);
15 }
16 void ini(){
17     for(int i=1;i<=n;i++){
18         belong[i].clear();
19         for(int j=1;j<=n;j++){
20             if(i==j) d[i][j]=0;
21             else d[i][j]=inf;
22         }
23     }
24     memset(vis,0,sizeof(vis));
25     for(int i=0;i<=m;i++)
26         region[i].clear();
27 }
28 int main(){
29     //freopen("in.txt","r",stdin);
30     while(~scanf("%d%d",&m,&n)){
31         ini();
32         scanf("%d",&l);
33         for(int i=0;i<l;i++)
34             scanf("%d",&club[i]);
35         for(int i=1;i<=m;i++){
36             scanf("%d",&num);
37             for(int j=0;j<num;j++){
38                 scanf("%d",&town);
39                 belong[town].push_back(i);
40                 region[i].push_back(town);
41             }
42             region[i].push_back(region[i][0]);
43             for(int j=0;j<num;j++){//有公共边即为相邻,赋值1
44                 int u=region[i][j],v=region[i][j+1];
45                 if(vis[u][v]) d[vis[u][v]][i]=d[i][vis[u][v]]=1;
46                 else vis[u][v]=vis[v][u]=i;
47             }
48         }
49         Floyd();
50         int dis,ans=inf;
51         for(int i=1;i<=m;i++){
52             dis=0;
53             for(int j=0;j<l;j++){
54                 int tmp=inf,c=club[j];
55                 for(int k=0;k<belong[c].size();k++)
56                     tmp=min(tmp,d[i][belong[c][k]]);
57                 dis+=tmp;
58             }
59             ans=min(ans,dis);
60         }
61         printf("%d\n",ans);
62     }
63     return 0;
64 }

时间: 2024-11-11 15:30:29

poj 1161 Floyd+枚举的相关文章

Stockbroker Grapevine (poj 1125 floyd + 枚举)

Language: Default Stockbroker Grapevine Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 27445   Accepted: 15211 Description Stockbrokers are known to overreact to rumours. You have been contracted to develop a method of spreading disinfo

poj1178 floyd+枚举

http://poj.org/problem?id=1178 Description Centuries ago, King Arthur and the Knights of the Round Table used to meet every year on New Year's Day to celebrate their fellowship. In remembrance of these events, we consider a board game for one player,

POJ 1161 Walls(最短路+枚举)

POJ 1161 Walls(最短路+枚举) 题目背景 题目大意:题意是说有 n个小镇,他们两两之间可能存在一些墙(不是每两个都有),把整个二维平面分成多个区域,当然这些区域都是一些封闭的多边形(除了最外面的一个),现在,如果某几个小镇上的人想要聚会,为选择哪个区域为聚会地点,可以使他们所有人总共需要穿过的墙数最小,题目上有说明,不在某个点上聚会(聚会点在某个多边形内部),行进过程中不穿过图中的点(也就是除出发点外的其他小镇). 输入第1行代表m(2<=M<=200)个区域 第2行代表n(3&

poj 1873 凸包+枚举

The Fortified Forest Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 6198   Accepted: 1744 Description Once upon a time, in a faraway land, there lived a king. This king owned a small collection of rare and valuable trees, which had been

Poj 1815 Friendship 枚举+求最小割

给以一个图和两个点S,T,问你拿掉最少多少个点可以使得S和T不连通.输出点数并且输出拿掉的是哪些点,如果有多种方法就输出字典序最小的那个. 这就是一个求最小点割集的问题.无向(有向)图G中,给定源点s和终点t,至少要删去多少个点(具体一点,删哪些点),使得s和t不连通.这个问题就是点连通度,也叫最小点割集. 解法其实理解起来不难,只要把图中的每一个点v拆成v',v''两个点,并建立<v',v''>权为1,这样就把最小点割集转化成求最小割的问题. 对于原图的转化也很简单,对于原来的每条边,转化成

poj 3977 Subset 枚举+二分

首先分成一半2^17和2^18,并且把其中一半变成相反数,然后枚举一半二分查找另一半,在找到的位置前后也找找. 这里用到了二级排序,有很多细节要处理,不多说了. 巨坑的一个地方就是,不能用系统的abs,要自己手写,简直坑死.. #include<cstdio> #include<algorithm> #include<iostream> #include<map> using namespace std; typedef long long ll; stru

POJ 3977Subset(枚举+二分)

Subset Time Limit: 30000MS   Memory Limit: 65536K Total Submissions: 1562   Accepted: 261 Description Given a list of N integers with absolute values no larger than 1015, find a non empty subset of these numbers which minimizes the absolute value of

USACO cowtour Floyd + 枚举

给出来的数据量还是可以的.题意:有若干个牧场,至少有两个不连通,一个牧场的直径就是牧场中最远的两个牧区的距离.要求找出几个牧场中最短的直径,就是找一条路径连接几个牧区,使这个直径最终最小. 基本方法,把整个图根据输入划分成几个不连通的牧区,然后求出每个牧区的直径(即每个连通块中的最长路径),然后枚举两个不在同一牧区的点,设blocks[i]记录第i个节点所在连通块的直径,那么result = min(blocks[i] + dis(i, j) + blocks[j]),可以用并查级判断两个点是否

POJ 1161 Walls【floyd 以面为点建图】

题目链接:http://poj.org/problem?id=1161 题目大意: 1.给出m个区域,n个俱乐部点.接下来是n个俱乐部点以及各个区域由什么点围成.求一个区域到各个俱乐部点的距离之和最小. 解题思路: 1.这题建图比较麻烦,以区域为点建图,区域之间若有边,则两区域的距离为1,建完图后跑一遍floyd就可以求出两两区域的最小距离. 2.对于答案,枚举每一个区域到各个俱乐部点的相邻区域的距离之和,取最小值. 1 #include<stdio.h> 2 #include<stri