【Havel定理判断可图化】POJ 1659

本文介绍了简单图的概念及其构造方法,重点讲解了Havel定理,并通过示例代码演示如何使用贪心算法来验证一组顶点度数序列是否可以构成简单图。

这里首先复习一下什么叫“简单图”(其实是自己忘记了==!).......

一个图如果不含重边或环则称为简单图

1 、Havel 定理:把度排序,从大到小,类似拓扑排序,只是把过程反过来而已。

具体过程:贪心的方法是每次把顶点按度大小从大到小排序,取出度最大的点 Vi,依次和度较大 的那些顶点 Vj 连接,同时减去 Vj 的度。连接完之后就不再考虑 Vi 了,剩下的点再次排 序然后找度最大的去连接……这样就可以构造出一个可行解。 判断无解有两个地方,若某次选出的 Vi 的度比剩下的顶点还多,则无解;若某次 Vj 的度 减成了负数,则无解。

2、 定理 1:总度和 mod 2=0。 

3 、定理 2:最大度<=n-1。 

#define N 10005

int g[11][11];
struct node{
    int id;
    int du;
}p[11];
bool cmp(node a,node b){
    return a.du>b.du;
}
bool gao(int n){
    int i,j;
    for(i=0;i<n;i++){
        sort(p+i,p+n,cmp);//对i后面的点度数大到小排序
        if(p[i].du<0)return false;//当出现点的度数<0表示不能构成简单图
        for(j=i+1;j<n && p[i].du>0;j++){//贪心,满足每个i点的度数,注意i点的度数>0才进行这一步!
            g[p[i].id][p[j].id] = g[p[j].id][p[i].id] = 1;
            p[j].du--;
            p[i].du--;
        }
    }
    return true;
}
int main(){
    int t;
    scanf("%d",&t);
    while(t--){
        int n;
        scanf("%d",&n);
        int i,j;
        for(i=0;i<n;i++){
            scanf("%d",&p[i].du);
            p[i].id = i;
        }
        memset(g,0,sizeof(g));
        if(gao(n)){
            puts("YES");
            for(i=0;i<n;i++){
                for(j=0;j<n;j++){
                    if(j)printf(" ");
                    printf("%d",g[i][j]);
                }
                puts("");
            }
        } else puts("NO");
        if(t)printf("\n");
    }
    return 0;
}

HDU 2454更简单,只需要判断是否可简单图化....




















Havel-Hakimi定理是一种用于判断一个序列是否能代表某个连通图的算法,它基于序列的排序规则。在C++中,你可以编写一个函数来检查一个序列是否满足Havel-Hakimi条件,如果满足则表示可以转为一个连通图。下面是一个简的实现: ```cpp #include <vector> #include <algorithm> bool havelHakimi(const std::vector<int>& sequence) { std::vector<int> degrees(sequence.size(), 0); bool is_connected = true; while (!degrees.empty()) { int largest_degree = -1; int max_degrees_index = -1; for (size_t i = 0; i < degrees.size(); ++i) { if (degrees[i] > largest_degree) { largest_degree = degrees[i]; max_degrees_index = i; } } // 如果当前序列有一个节点的度大于1,则尝试移除边 if (largest_degree > 1) { degrees[max_degrees_index]--; degrees[sequence[max_degrees_index] - 1]--; } else { // 当所有节点的度都不超过1时,表示无法形成连通图 is_connected = false; break; } // 将剩余的节点按顺序放回 while (max_degrees_index >= 1 && sequence[max_degrees_index] == 0) { sequence[max_degrees_index] = degrees.back(); degrees.pop_back(); max_degrees_index--; } } return is_connected; } std::vector<int> make_graph_sequence(size_t n) { // 例如,构造一个长度为n的序列,每个节点有n-1条边 std::vector<int> sequence(n); for (size_t i = 0; i < n; ++i) { sequence[i] = n - 1; } return sequence; } int main() { auto sequence = make_graph_sequence(4); // 构造一个四节点的序列 bool isValid = havelHakimi(sequence); if (isValid) { printf("The sequence represents a connected graph.\n"); } else { printf("The sequence does not represent a connected graph.\n"); } return 0; } ``` 这段代码首先生成一个序列,其中每个节点都有n-1条边。然后,它将按照Havel-Hakimi算法进行测试。如果最后能得到非空的`degrees`向量,那么说明序列可以构建一个连通图。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值