题意 : 

在某国,城市之间建起了长城,每一条长城连接两座城市。每条长城互不相交。因此,从一个区域到另一个区域,需要经过一些城镇或者穿过一些长城。任意两个城市A和B之间最多只有一条长城,一端在A城市,另一端在B城市。从A走到B,可以只在一个区域内行走,或者只在长城上行走。

有一个俱乐部,它的会员分布在不同的城市中,每个城市要么只有一个会员,要么没有会员。会员们决定要集中到一个区域内聚会。他们骑车前往目的地。首先,由于城市内交通太堵,他们不想进入任何一个城市内,其次,他们希望穿越尽可能少的长城。他们确定一个聚会的区域之后,有的会员要穿越多条长城才能到达聚会区域,有的会员则可能本身就住在这个区域边上的城市所以不需穿越任何长城。他们希望找到一个区域,使得所有会员穿越长城的数量之和最小。

一共有N座城市,城市从1到N编号。如图一所示,有编号的顶点表示城市,每一条边表示一条长城。假设有3个会员,分别住在城市3、6和9,则最佳聚会区域和每个会员的路线如图二所示。共需穿越长城条数是2:城市9的会员需要穿越城市2和城市4之间的长城,城市6的会员需要穿越城市4和7之间的长城。给出城市、区域以及每个会员所在的城市,编一个程序,确定一个最佳的聚会区域,使得需要穿越长城的数量之和最小。

分析 :

这题先将各个区域抽象成点,然后每个区域之间如果有边相连 ( 例如题目所给图的 2、4、3、7 和 4、5、8 只通过了一个点相连,所以不算边相连 ) 那么就将这两个区域连接一条边权为 1 的点,然后对于各个城市如果它在某个区域的边缘上,那么就连一条城市到区域点且边权为 0 的有向边 ( 只是为了能让城市和区域之间有相连 ),最后根据这幅图去跑 Floyd 然后枚举区域点作为会员们聚集的点计算贡献取最小即可。这里的判断边相邻的方法,由于图的区域描述是按点顺时针给出(除了最后一个“外部区域”),所以可以根据这个特性,来用点的顺序描述一条边,比如开个数组 info[a][b] = 1 即 a 和 b 相连的边属于区域 1 ,如果下次再碰到有顺序 a、b 的边,那么说明此时这个区域和 1 边相连了,当然在判断的时候 info 里面的顺序是逆序的,而新判断的边是顺序的,至于为什么,模拟一下就知道了!

#include<stdio.h>
#include<algorithm>
#include<set>
#include<math.h>
using namespace std;
;
const int  INF = 0x3f3f3f3f;
int N, M, L;
];
int tmp[maxn];
int info[maxn][maxn];///info[a][b] = c ==> 城市 a、b 之间的边属于区域 c
int dp[maxn][maxn];///跑 Floyd 的邻接矩阵
bool Belong[maxn][maxn];///Belong[a][b] = true ==> 区域 a 包含了点 b,false则反之,一开始初始化为 false

int main(void)
{
    while(~scanf("%d %d %d", &M, &N, &L)){
        ; i<L; i++)
            scanf("%d", &Members[i]);

        ; i<=M+N; i++){
            ; j<=M+N; j++){
                ;
                if(i<=N && j<=M) Belong[i][j] = false;
                dp[i][j] = (i==j) ?  : INF;
            }
        }

        ; i<=M; i++){
            int num;
            scanf("%d", &num);
            ; j<num; j++){
                scanf("%d", &tmp[j]);
                Belong[i][tmp[j]] = true;
                //Belong[i].insert(tmp[j]);
                dp[tmp[j]+M][i] = ; ///连一条城市到这个区域边权为 0 的边
            }

            //if(i == M) std::reverse(tmp, tmp+num);///最后的边是逆序的,一开始没想明白,其实如果倒序了就是错了
            ; j<num; j++){
                )%num]];
                ) info[tmp[(j+)%num]][tmp[j]] = i;///判断是否有边相连的情况,注意一下正顺和逆序
                ;
            }
        }

//        for(int i=1; i<=M+N; i++){
//            for(int j=1; j<=M+N; j++){
//                if(dp[i][j] == INF) printf("x ");
//                else printf("%d ", dp[i][j]);
//            }puts("");
//        }puts("");

        ; k<=M+N; k++)
            ; i<=M+N; i++)
                ; j<=M+N; j++)
                    dp[i][j] = min(dp[i][j], dp[i][k]+dp[k][j]);

        int ans = INF;
        ; i<=M; i++){///枚举集合的区域
            ;
            ; j<L; j++){
                if(Belong[i][Members[j]]) continue;
                sum += dp[Members[j]+M][i];///计算贡献
            }
            ans = min(ans, sum);
        }

        printf("%d\n", ans);
    }
    ;
}

POJ 1161 Walls ( Floyd && 建图 )的更多相关文章

  1. POJ 1161 Walls(最短路+枚举)

    POJ 1161 Walls(最短路+枚举) 题目背景 题目大意:题意是说有 n个小镇,他们两两之间可能存在一些墙(不是每两个都有),把整个二维平面分成多个区域,当然这些区域都是一些封闭的多边形(除了 ...

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

    题目链接:http://poj.org/problem?id=1161 题目大意: 1.给出m个区域,n个俱乐部点.接下来是n个俱乐部点以及各个区域由什么点围成.求一个区域到各个俱乐部点的距离之和最小 ...

  3. poj 3281 最大流+建图

    很巧妙的思想 转自:http://www.cnblogs.com/kuangbin/archive/2012/08/21/2649850.html 本题能够想到用最大流做,那真的是太绝了.建模的方法很 ...

  4. poj 1161 Walls

    https://vjudge.net/problem/POJ-1161 题意:有m个区域,n个小镇,有c个人在这些小镇中,他们要去某一个区域中聚会,从一个区域到另一个区域需要穿墙,问这些人聚到一起最少 ...

  5. POJ 1637 Sightseeing tour 建图+网络流

    题意: 给定一个混合图,所谓混合图就是图中既有单向边也有双向边,现在求这样的图是否存在欧拉回路. 分析: 存在欧拉回路的有向图,必须满足[入度==出度],现在,有些边已经被定向,所以我们直接记录度数即 ...

  6. POJ 1149 网络流 合并建图

    这个题目我敲了一个简单的EK,这不是难点 难点在于建图,按题目的要求 每个猪圈和顾客都建点的话,那也太多了...我看了Edelweiss里面的缩点方法才建好的图,哎,惭愧啊 实际那些猪圈根本不需要单独 ...

  7. POJ 1161 Walls(Floyd , 建图)

    题意: 给定n个城市, 然后城市之间会有长城相连, 长城之间会围成M个区域, 有L个vip(每个vip会处于一个城市里)要找一个区域聚会, 问一共最少跨越多少个长城. 分析: 其实这题难就难在建图, ...

  8. POJ - 1149 PIGS (建图思维+最大流)

    (点击查看原题) 题目分析 (以下均为 Edelweiss 大佬的思路,博主承认自己写不了这么好,但是学习的心促使我记录下这个好题的写法,所以代码是我写的) [题目大意] 有 M 个猪圈,每个猪圈里初 ...

  9. poj 3281 最大流建图

    题目链接:http://poj.org/problem?id=3281 #include <cstdio> #include <cmath> #include <algo ...

随机推荐

  1. 2019暑假第二周(hadoop在个人电脑上的搭建)

    一,Hadoop和NoSQL数据库的学习,大多需要Linux环境. 搭建Linux环境可以分为两种方式: (1)在电脑上安装双操作系统,即同时安装Linux和Windows操作系统,在电脑启动的时候, ...

  2. Java中个容器的对比

    List: 有序,列表存储,元素可重复 Set: 无序,元素不可重复 Map:无序,元素可重复,key不能重复 LinkedList :链表,删除和添加效率很高,随机访问效率较ArrayList类低, ...

  3. 深度学习之美(张玉宏)——第四章 人生苦短我用python

    1 函数参数 (1)收集参数:以一个星号*加上形参名的方式,表示这个函数的实参个数不定,可能0个可能n个. def varParaFun(name,*param): print('位置参数是:',na ...

  4. 15.永恒之蓝exp----

    永恒之蓝exp 2017年,影响于全世界 SMB ripid7官网获取ms17-010的exp信息 Rapid7: https://www.rapid7.com/db/modules/exploit/ ...

  5. python调用java所有代码都要放在jvm开启的时候调用,否则报错: No matching overloads found for in find. at native\common\jp_method.cpp:127

    1.解决方法 开启java虚拟机 jvm 或者先执行结束在关闭java虚拟机jvm

  6. 【Qt开发】事件循环与线程 二

    事件循环与线程 二 Qt 线程类 Qt对线程的支持已经有很多年了(发布于2000年九月22日的Qt2.2引入了QThread类),Qt 4.0版本的release则对其所有所支持平台默认地是对多线程支 ...

  7. [LeetCode] 1092. Shortest Common Supersequence

    LeetCode刷题记录 传送门 Description Given two strings str1 and str2, return the shortest string that has bo ...

  8. 获取kafka最新offset-scala

    无论是在spark streaming消费kafka,或是监控kafka的数据时,我们经常会需要知道offset最新情况 kafka数据的topic基于分区,并且通过每个partition的主分区可以 ...

  9. python中,a=10.0 b=10.0 a is b 为什么输出是false

    >>>a=10.0>>>b=10.0>>>a is bFalse为什么当a=10,b=10时,a is b输出的是True呢? >>& ...

  10. 【LGR-063】洛谷11月月赛 I & MtOI2019 Ex Div.2 (A-C)

    [MtOI2019]黑蚊子多 : 按题意模拟 #include<iostream> #include<cstdio> #include<cstring> using ...