hd 1689 Alien’s Necklace[转自剑哥的代码]
来源:互联网 发布:塔米智能 知乎 编辑:程序博客网 时间:2024/06/03 19:12
// HDU Online Judge
// Problem 1689 Alien’s Necklace
// Algorithm: Enumerate + BFS
// ---- 对每一个顶点,计算经过该顶点的最短环路长,计算方法为 BFS:
// ---- 在BFS中,如果遇到访问过的点,如果访问过的点是BFS隐式树中当前点的祖先,
// ---- 那么该回路不经过我们枚举的点,我们按照“假设当前回路经过枚举点”计算
// ---- 回路长度,由于该长度总是不小于最终最短环路长,所以对最优解不影响。
// ---- 当枚举完所有顶点,也就得到了最短环路长度。
// Complexity: O(VE), V为顶点数,E为边数
// Author: obtuseSword
// Date: 2008-05-11
// Compiler: Visual Studio 2005
#include <cstdio>
#include <vector>
#include <queue>
using namespace std;
vector<int> adj[1001]; // 邻接表
// 读入邻接关系,创建关系图(邻接表)
void create_graph(int n,int m);
// 计算满足条件的最短环路的长度
int min_circle(int n);
//--------------------- 主函数 ---------------------//
//--------------------- 开始 ---------------------//
int main()
{
int T; // 测试数据组数
scanf("%d",&T);
for(int t=1; t<=T; t++){
// 读入数据
int n, m; // 顶点数,边数
scanf("%d%d",&n,&m);
create_graph(n,m);
// 求解
int len = min_circle(n);
// 输出结果
printf("Case %d: ",t);
if( len == -1 )
printf("Poor JYY. ");
else
printf("JYY has to use %d balls. ",len);
}
return 0;
}
//--------------------- 主函数 ---------------------//
//--------------------- 结束 ---------------------//
// 函数:读入邻接关系,创建邻接表
void create_graph(int n,int m){
// 清空邻接表
for(int i=1; i<=n; i++)
adj[i].clear();
// 读入邻接关系
for(int j=0; j<m; j++){
int a,b;
scanf("%d%d",&a,&b);
adj[a].push_back(b);
adj[b].push_back(a);
}
}
// 函数:计算经过奇数个顶点的最短环路长
int min_circle(int n){
int min_len = n+1; // 最短环路长
// 枚举环路搜索的起始点
for(int i=1; i<=n; i++){
vector<bool> visited(n+1,false); // 已访问标志
vector<int> depth(n+1); // 已访问的顶点的深度
int present_len = 0; // 已搜索的深度
// 添加搜索起始点
queue<int> que;
que.push(i);
visited[i] = true;
depth[i] = 0;
// 宽度优先搜索(BFS),以已求得的最短环路长为阈值
while( !que.empty() && ++present_len < min_len ){
vector<int> extended; // 用于临时保存当前扩展出的顶点
// 不断扩展新的层
while( !que.empty() ){
int v = que.front(); // 被扩展的顶点
que.pop();
// 扩展出更深一层
for(vector<int>::iterator iter = adj[v].begin(); iter != adj[v].end(); iter++){
// 如果发现回路
if( visited[*iter] ){
// 假定经过顶点 i 所构成的环路的长度
int cir_len = present_len + depth[*iter];
// 回路要满足“经过奇数个顶点”
if( cir_len % 2 && cir_len < min_len )
min_len = cir_len;
// 如果未发现回路
}else{
// 新顶点先暂存在 extended 中
extended.push_back(*iter);
// 记录相关信息
visited[*iter] = true;
depth[*iter] = present_len;
}
}
}
// 将当前扩展出的顶点加入 FIFO 队列中
for(vector<int>::iterator iter = extended.begin(); iter != extended.end(); iter++)
que.push(*iter);
}
}
// 返回结果,以 -1 表示不存在满足条件的回路
return min_len == n+1 ? -1 : min_len;
}
// Problem 1689 Alien’s Necklace
// Algorithm: Enumerate + BFS
// ---- 对每一个顶点,计算经过该顶点的最短环路长,计算方法为 BFS:
// ---- 在BFS中,如果遇到访问过的点,如果访问过的点是BFS隐式树中当前点的祖先,
// ---- 那么该回路不经过我们枚举的点,我们按照“假设当前回路经过枚举点”计算
// ---- 回路长度,由于该长度总是不小于最终最短环路长,所以对最优解不影响。
// ---- 当枚举完所有顶点,也就得到了最短环路长度。
// Complexity: O(VE), V为顶点数,E为边数
// Author: obtuseSword
// Date: 2008-05-11
// Compiler: Visual Studio 2005
#include <cstdio>
#include <vector>
#include <queue>
using namespace std;
vector<int> adj[1001]; // 邻接表
// 读入邻接关系,创建关系图(邻接表)
void create_graph(int n,int m);
// 计算满足条件的最短环路的长度
int min_circle(int n);
//--------------------- 主函数 ---------------------//
//--------------------- 开始 ---------------------//
int main()
{
int T; // 测试数据组数
scanf("%d",&T);
for(int t=1; t<=T; t++){
// 读入数据
int n, m; // 顶点数,边数
scanf("%d%d",&n,&m);
create_graph(n,m);
// 求解
int len = min_circle(n);
// 输出结果
printf("Case %d: ",t);
if( len == -1 )
printf("Poor JYY. ");
else
printf("JYY has to use %d balls. ",len);
}
return 0;
}
//--------------------- 主函数 ---------------------//
//--------------------- 结束 ---------------------//
// 函数:读入邻接关系,创建邻接表
void create_graph(int n,int m){
// 清空邻接表
for(int i=1; i<=n; i++)
adj[i].clear();
// 读入邻接关系
for(int j=0; j<m; j++){
int a,b;
scanf("%d%d",&a,&b);
adj[a].push_back(b);
adj[b].push_back(a);
}
}
// 函数:计算经过奇数个顶点的最短环路长
int min_circle(int n){
int min_len = n+1; // 最短环路长
// 枚举环路搜索的起始点
for(int i=1; i<=n; i++){
vector<bool> visited(n+1,false); // 已访问标志
vector<int> depth(n+1); // 已访问的顶点的深度
int present_len = 0; // 已搜索的深度
// 添加搜索起始点
queue<int> que;
que.push(i);
visited[i] = true;
depth[i] = 0;
// 宽度优先搜索(BFS),以已求得的最短环路长为阈值
while( !que.empty() && ++present_len < min_len ){
vector<int> extended; // 用于临时保存当前扩展出的顶点
// 不断扩展新的层
while( !que.empty() ){
int v = que.front(); // 被扩展的顶点
que.pop();
// 扩展出更深一层
for(vector<int>::iterator iter = adj[v].begin(); iter != adj[v].end(); iter++){
// 如果发现回路
if( visited[*iter] ){
// 假定经过顶点 i 所构成的环路的长度
int cir_len = present_len + depth[*iter];
// 回路要满足“经过奇数个顶点”
if( cir_len % 2 && cir_len < min_len )
min_len = cir_len;
// 如果未发现回路
}else{
// 新顶点先暂存在 extended 中
extended.push_back(*iter);
// 记录相关信息
visited[*iter] = true;
depth[*iter] = present_len;
}
}
}
// 将当前扩展出的顶点加入 FIFO 队列中
for(vector<int>::iterator iter = extended.begin(); iter != extended.end(); iter++)
que.push(*iter);
}
}
// 返回结果,以 -1 表示不存在满足条件的回路
return min_len == n+1 ? -1 : min_len;
}
- hd 1689 Alien’s Necklace[转自剑哥的代码]
- hdu 1689 Alien’s Necklace
- hdu 1689 Alien’s Necklace (bfs层次图剪枝)
- hdu1689 Alien’s Necklace--BFS & 奇偶标记
- hdu 1689 Alien’s Necklace(bfs搜索最小奇数环)
- A - Alien's Organ
- ZOJ3696 Alien's Organ
- 自己的usaco代码---PROB Broken Necklace
- zoj 3696 Alien's Organ
- ZOJ 3696 Alien's Organ
- zoj 3696 Alien's Organ
- 实现 QQLive HD 界面的代码
- Alien的排列
- alien的安装
- ZOJ 3696 Alien's Organ
- lua的FFI库--alien
- lua的FFI库--alien
- HD 1161 Eddy's mistakes
- Struts 2与AJAX(第一部分)
- Tomcat 常见错误
- MFC程序逆向 – 消息篇(下)
- 博客终于可以写了
- asp.net 中cross page autopaost(跨页面的窗体回发事件)
- hd 1689 Alien’s Necklace[转自剑哥的代码]
- asp.net事件驱动处理程序
- 谈谈数字图像的缩放算法
- 开张
- 关于栈和堆中变量的作用域问题
- javascript选择一个项目
- YUV420 和RGB之间的转换的程序,YUV采样频率采用cif
- 『VC++技术内幕』学习笔记
- 我喜欢的车牌被人占用