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;
}

原创粉丝点击