题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5876

题意:

  有一个 n 个点无向图,再给你 m 对顶点, 代表着这 m 对顶点之间没有边, 除此之外每两个点之间都有一条边, 且权值为 1.然后还有一个源点 S, 让你计算源点到其他各点之间的最短距离,如果不存在则输出 -1.也就是说让你在所给的图的补图上求源点到其他各点的最短路径.

思路:

  补图上求最短路径算是比较经典的题.在这里所求的最短路其实并不需要用到 dijkstra 之类的算法,由于每条边之间的距离都为 1,每条边的权值一样.那么就可以想到这个做法:

  步骤1:根据题意建图.然后建立一个队列,把源点 S 压入队列,其他的各个点存到另一个集合 V 里, 并建立一个数组来存储源点到其他各点的最短距离,初始化为 -1, dis[S] = 0.

  步骤2:从队列首部取出一个节点 v,访问所有与节点 v 不相邻的节点 u,把 u 压入到队列尾部, 并从集合 V 中把 u 除去, 更新dis[u] = dis[v] + 1.

  步骤3:反复重复步骤 2, 直到队列为空.之后 dis 数组里保存的就是答案.

  解决了怎么做之后,还没有完,由于题目给的点数非常大,所以还需要优化下时间.这里比较费时间的就是步骤 2 中的找不相邻的点.这里就可以用 STL 中的 set 来维护集合 V, 也就是未被访问到的点. 初始化 set1 中为所有点(除去源点 S), 当访问的点 v 时, 在 set1 中除去与点 v 相邻的点 u, 并加入到 set2 中,那么 set1 中剩下的点就是所有与点 v 不相邻的点, 依次遍历压入队列. 之后再把 set2 拷贝到 set1, 那么 set1 就是剩下的未被访问到的点,如此反复下去.可以看到,对于每条边只访问一次.每个点也只进一次队列.所以总的时间复杂度为 O(n * m),可以达到要求了.

notes:建立 无向图 的时候每条边要存两次. 所以数组的大小一定是原题所给的边数的两倍! 两倍! 两倍!顺便求一个用链表实现的代码,自己用链表没写出来.(我好菜啊.jpg

代码:

 #include <iostream>
#include <cstdio>
#include <queue>
#include <set>
#include <cstring>
#include <algorithm> using namespace std;
typedef long long LL; const int MAXN = ;
const int MAXE = ;
int n, m, T, S;
int dis[MAXN + ];//保存最终的最短距离 int head[MAXN + ], len; //链式前向星
struct NODE {int to; int next; };
NODE edge[ * MAXE + ]; void addedge(int u, int v) { //链式前向星加边
edge[len].to = v;
edge[len].next = head[u];
head[u] = len++;
} void BFS() { //从起点开始BFS
memset(dis, -, sizeof(dis));
queue <int> Qu;
Qu.push(S); dis[S] = ; //起点初始化
set<int> unsed, hep; //用来维护尚未被访问的点
for(int i = ; i <= n; i++) unsed.insert(i);
unsed.erase(S);
while( !Qu.empty() ) {
int tp = Qu.front(); Qu.pop();
for(int k = head[tp]; k != -; k = edge[k].next) { //从 unsed 中除去和当前拓展节点相邻的点,同时加入到临时辅助的集合中
if(unsed.find(edge[k].to) != unsed.end()) {
unsed.erase(edge[k].to);
hep.insert(edge[k].to);
}
}
for(set<int>::iterator it = unsed.begin(); it != unsed.end(); it++) {// unsed 暂时保存的是和当前拓展节点不相邻的点
Qu.push(*it);
dis[*it] = dis[tp] + ;
}
hep.swap(unsed), hep.clear();//从辅助集合中 copy 剩下的未被访问到的点.
}
} int main() {
scanf("%d", &T);
while(T--) {
memset(head, -, sizeof(head));
scanf("%d%d", &n, &m);
int u, v; len = ;
for(int i = , len = ; i < m; i++) {
scanf("%d%d", &u, &v);
addedge(u, v); addedge(v, u);
}
scanf("%d", &S);
BFS();
for(int i = , j = ; i <= n; i++) if(i != S) printf("%d%c", dis[i], " \n"[++j == n - ]);
}
return ;
}

HDU 5876 Sparse Graph(补图上BFS)的更多相关文章

  1. hdu 5876 Sparse Graph 无权图bfs求最短路

    Sparse Graph Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others) P ...

  2. HDU 5876 Sparse Graph 【补图最短路 BFS】(2016 ACM/ICPC Asia Regional Dalian Online)

    Sparse Graph Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)To ...

  3. HDU 5876 Sparse Graph BFS 最短路

    Sparse Graph Problem Description   In graph theory, the complement of a graph G is a graph H on the ...

  4. HDU 5876 Sparse Graph

    Sparse Graph Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)To ...

  5. HDU 5876 Sparse Graph(补图中求最短路)

    http://acm.hdu.edu.cn/showproblem.php?pid=5876 题意: 在补图中求s到其余各个点的最短路. 思路:因为这道题目每条边的距离都是1,所以可以直接用bfs来做 ...

  6. HDU 5876 Sparse Graph BFS+set删点

    Problem Description In graph theory, the complement of a graph G is a graph H on the same vertices s ...

  7. hdu 5876 Sparse Graph icpc大连站网络赛 1009 补图最短路

    BFS+链表 代码改自某博客 #include<stdio.h> #include<iostream> #include<algorithm> #include&l ...

  8. HDU 5867 Sparse Graph (2016年大连网络赛 I bfs+补图)

    题意:给你n个点m条边形成一个无向图,问你求出给定点在此图的补图上到每个点距离的最小值,每条边距离为1 补图:完全图减去原图 完全图:每两个点都相连的图 其实就是一个有技巧的bfs,我们可以看到虽然点 ...

  9. HDU 5876 关于补图的bfs

    1.HDU 5876  Sparse Graph 2.总结:好题,把STL都过了一遍 题意:n个点组成的完全图,删去m条边,求点s到其余n-1个点的最短距离. 思路:把点分为两个集合,A为所有没有到达 ...

随机推荐

  1. 子集系列(一) 传统subset 问题,例 [LeetCode] Subset, Subset II, Bloomberg 的一道面试题

    引言 Coding 问题中有时会出现这样的问题:给定一个集合,求出这个集合所有的子集(所谓子集,就是包含原集合中的一部分元素的集合). 或者求出满足一定要求的子集,比如子集中元素总和为定值,子集元素个 ...

  2. div 画table尝试

    .left { float: left; } .table { border: solid 1px black; width: 750px; } .tr { width: 100%; height: ...

  3. linux之nginx的安装

    (一)这次是自己折腾服务器的环境,所以自己算是都装过一遍,在装的过程中也是在网上搜索,其实最后在公司运维的指导下知道自己安装出错在哪里的.不说了,直接说安装和问题 (二):首先从 http://ngi ...

  4. NOIP模拟赛9

    T1U3348 A2-回文数 https://www.luogu.org/problem/show?pid=U3348 考场上钻了牛角尖了,然后0分 #include<cstdio> #i ...

  5. HDU 2582 规律 素因子

    定义$Gcd(n)=gcd(\binom{n}{1},\binom{n}{2}...\binom{n}{n-1})$,$f(n)=\sum_{i=3}^{n}{Gcd(i)}$,其中$(3<=n ...

  6. C#为何不推荐在构造函数中访问虚成员

    如果在一个类中定义了虚属性或者虚方法,又在构造函数中访问了这个虚属性或方法,此时VisualStudio是不会给出警告,并且编译也没有问题,但是如果安装了Resharper插件则会给出警告提示:&qu ...

  7. 数据库 插入时 碰到NULL报错判断的一种方法(技巧)

    //public static object ToDBNull(object value) 判断插入数据的时候个别参数不能为空的时候做的判断方法 //{ // if (value == null) / ...

  8. android ViewPager之OnPageChangeListener接口

    项目中在使用ViewPager的时候,一般都要在界面滑动的时候做一些事情,android中有个专门的状态回调接口OnPageChangeListener. /** * Callback interfa ...

  9. PIP安装时报The repository located at pypi.douban.com is not a trusted or secure host and is being ignore

    C:\WINDOWS\system32>pip install scrapyCollecting scrapy The repository located at pypi.douban.com ...

  10. java关键字(详解)

    目录 1. 基本类型 1) boolean 布尔型 2) byte 字节型 3) char 字符型 4) double 双精度 5) float 浮点 6) int 整型 7) long 长整型 8) ...