hdoj 3435 A new Graph Game 【无向图判断权值最小哈密顿环】【KM算法】

A new Graph Game

Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)

Total Submission(s): 1934    Accepted Submission(s): 827

Problem Description

An undirected graph is a graph in which the nodes are connected by undirected arcs. An undirected arc is an edge that has no arrow. Both ends of an undirected arc are equivalent--there is no head or tail. Therefore, we represent an edge in an undirected graph
as a set rather than an ordered pair.

Now given an undirected graph, you could delete any number of edges as you wish. Then you will get one or more connected sub graph from the original one (Any of them should have more than one vertex).

You goal is to make all the connected sub graphs exist the Hamiltonian circuit after the delete operation. What’s more, you want to know the minimum sum of all the weight of the edges on the “Hamiltonian circuit” of all the connected sub graphs (Only one “Hamiltonian
circuit” will be calculated in one connected sub graph! That is to say if there exist more than one “Hamiltonian circuit” in one connected sub graph, you could only choose the one in which the sum of weight of these edges is minimum).

For example, we may get two possible sums:

(1)  7 + 10 + 5 = 22

(2)  7 + 10 + 2 = 19

(There are two “Hamiltonian circuit” in this graph!)

Input

In the first line there is an integer T, indicates the number of test cases. (T <= 20)

In each case, the first line contains two integers n and m, indicates the number of vertices and the number of edges. (1 <= n <=1000, 0 <= m <= 10000)

Then m lines, each line contains three integers a,b,c ,indicates that there is one edge between a and b, and the weight of it is c . (1 <= a,b <= n, a is not equal to b in any way, 1 <= c <= 10000)

Output

Output “Case %d: “first where d is the case number counted from one. Then output “NO” if there is no way to get some connected sub graphs that any of them exists the Hamiltonian circuit after the delete operation. Otherwise, output the minimum sum of weight
you may get if you delete the edges in the optimal strategy.

Sample Input

3

3 4
1 2 5
2 1 2
2 3 10
3 1 7 

3 2
1 2 3
1 2 4

2 2
1 2 3
1 2 4

Sample Output

Case 1: 19
Case 2: NO
Case 3: 6

Hint

In Case 1:
You could delete edge between 1 and 2 whose weight is 5. 

In Case 2:
It’s impossible to get some connected sub graphs that any of them exists the Hamiltonian circuit after the delete operation.

题意:给你一个N个点M条无向边的图。问你存不存在哈密顿环,若不存在输出NO,反之输出 权值之和最小的哈密顿环。

思路:费用流我不会写o(╯□╰)o,TLE到死 。   KM算法直接就过了,无奈了。

气死了!!! 又把做过的费用流用KM刷了一遍。以后碰到这样的题目果断KM,费用流先靠边。

AC代码:2458ms

#include <cstdio>
#include <cstring>
#include <algorithm>
#define INF 0x3f3f3f3f
#define MAXN 1010
using namespace std;
int lx[MAXN], ly[MAXN];
int Map[MAXN][MAXN];
bool visx[MAXN], visy[MAXN];
int slack[MAXN];
int match[MAXN];
int N, M;
void getMap()
{
    for(int i = 1; i <= N; i++)
    {
        for(int j = 1; j <= N; j++)
            Map[i][j] = -INF;//初始化
    }
    int a, b, c;
    while(M--)
    {
        scanf("%d%d%d", &a, &b, &c);
        if(-c > Map[a][b])//去重
            Map[a][b] = Map[b][a] = -c;
    }
}
int DFS(int x)
{
    visx[x] = true;
    for(int y = 1; y <= N; y++)
    {
        if(visy[y]) continue;
        int t = lx[x] + ly[y] - Map[x][y];
        if(t == 0)
        {
            visy[y] = true;
            if(match[y] == -1 || DFS(match[y]))
            {
                match[y] = x;
                return 1;
            }
        }
        else if(slack[y] > t)
            slack[y] = t;
    }
    return 0;
}
int k = 1;
void KM()
{
    memset(match, -1, sizeof(match));
    memset(ly, 0, sizeof(ly));
    for(int x = 1; x <= N; x++)
    {
        lx[x] = -INF;
        for(int y = 1; y <= N; y++)
            lx[x] = max(lx[x], Map[x][y]);
    }
    for(int x = 1; x <= N; x++)
    {
        for(int i = 1; i <= N; i++)
            slack[i] = INF;
        while(1)
        {
            memset(visx, false, sizeof(visx));
            memset(visy, false, sizeof(visy));
            if(DFS(x)) break;
            int d = INF;
            for(int i = 1; i <= N; i++)
            {
                if(!visy[i] && slack[i] < d)
                    d = slack[i];
            }
            for(int i = 1; i <= N; i++)
            {
                if(visx[i])
                   lx[i] -= d;
            }
            for(int i = 1; i <= N; i++)
            {
                if(visy[i])
                    ly[i] += d;
                else
                    slack[i] -= d;
            }
        }
    }
    //判断是否存在完美匹配
    int ans = 0;
    bool flag = true;
    for(int i = 1; i <= N; i++)
    {
        if(match[i] == -1 || Map[match[i]][i] == -INF)
        {
            flag = false;
            break;
        }
        ans += Map[match[i]][i];
    }
    printf("Case %d: ", k++);
    if(flag)
        printf("%d\n", -ans);
    else
        printf("NO\n");
}
int main()
{
    int t;
    scanf("%d", &t);
    while(t--)
    {
        scanf("%d%d", &N, &M);
        getMap();
        KM();
    }
    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2025-01-24 00:13:36

hdoj 3435 A new Graph Game 【无向图判断权值最小哈密顿环】【KM算法】的相关文章

HDU 4738 --Caocao&#39;s Bridges 【无向图边双联通 &amp;&amp; 求权值最小的桥 &amp;&amp; 模板】

Caocao's Bridges Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2641    Accepted Submission(s): 855 Problem Description Caocao was defeated by Zhuge Liang and Zhou Yu in the battle of Chibi. B

hdu Caocao&#39;s Bridges(无向图边双连通分量,找出权值最小的桥)

1 /* 2 题意:给出一个无向图,去掉一条权值最小边,使这个无向图不再连同! 3 4 tm太坑了... 5 1,如果这个无向图开始就是一个非连通图,直接输出0 6 2,重边(两个节点存在多条边, 权值不一样) 7 3,如果找到了桥的最小权值为0,也就是桥上的士兵数为0,那么还是要最少派一个 8 士兵过去炸掉桥! 9 10 思路:假设每两个节点最多只有一条边进行相连! 11 进行tarjan算法,如果该算法调用了超过2次,说明这个原图就是不连通的! 12 否则在tarjan算法中将桥存起来!然后

hdu 1853 Cyclic Tour &amp;&amp; hdu 3435 A new Graph Game(简单KM算法)

Cyclic Tour Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/65535 K (Java/Others) Total Submission(s): 1478    Accepted Submission(s): 750 Problem Description There are N cities in our country, and M one-way roads connecting them. Now L

HDU 3435 A new Graph Game(最小费用流:有向环权值最小覆盖)

http://acm.hdu.edu.cn/showproblem.php?pid=3435 题意:有n个点和m条边,你可以删去任意条边,使得所有点在一个哈密顿路径上,路径的权值得最小. 思路: 费用流,注意判断重边,否则会超时. 1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstring> 5 #include<queue> 6 using names

算法之判断一个图是否有环

在一些经典算法中,经常需要判断一些图是否具有环路,比如拓扑排序,需要在最初判断该图是否有环路,如有有环路,则无法找到最长的一条线,比如dijkstra算法,每找到一条最短的边,都要判断找到的边和现有的树是否已经构成了环路. 因此,在这篇博客,我们重点来说一个判断图是否有环的算法. 首先我们介绍一个对于无向图和有向图通用的算法,先讲算法思路: 1.统计各个图中各个点的入度数(能够到达这个点的点). 2.然后找出入度数为0的点(无向图找入度数为1的点). 3.删除入度数为0的点,将其边也删除. 4.

判断图中是否有环的方法

一.无向图 方法一:n算法: 原理是: 如果存在回路,则必存在一个子图,是一个环路.环路中所有顶点的度>=2. 第一步:删除所有度<=1的顶点及相关的边,并将另外与这些边相关的其它顶点的度减一. 第二步:将度数变为1的顶点排入队列,并从该队列中取出一个顶点重复步骤一. 如果最后还有未删除顶点,则存在环,否则没有环. 方法2: DFS搜索图,图中的边只可能是树边或反向边,一旦发现反向边,则表明存在环.该算法的复杂度为O(V). 二.有向图 主要有深度优先和拓扑排序两种方法 判断图中是否有环的方法

HDOJ 3790 最短路径问题 【双权值】

题意:... 难点:如何处理两个权值. 分析:题意说如果最短路径有多个,那么取价值最低的那个,所以说价值随着路径在变,如果路径不相等那么就更新路径并且更新价值,反之,则判断价值是不是要更新. 代码: #include<stdio.h> #include<string.h> #define M 1002 #define INF 0x3f3f3f3f int mapp[M][M], mapd[M][M], n, m, di[M], dp[M];//mapd是路径 mapp是价值 boo

HDOJ 3790 双权值Dijkstra

1 #include <iostream> 2 #include <stdio.h> 3 #include <string.h> 4 #include <cstring> 5 using namespace std; 6 7 const int INF = 1000000; 8 const int MAXSIZE = 1005; 9 10 int map[MAXSIZE][MAXSIZE]; 11 int price[MAXSIZE][MAXSIZE]; 1

判断单向链表是否有环,环起点,环长,链表长

今天在微信上看到一篇介绍如何判断单向链表是否有环的文章,感觉很有意思,整理一下读后的思路. 一.判断单向链表是否有环 方法1:设置一个Hashset,顺序读取链表中的节点,判断Hashset中是否有该节点的唯一标识(ID).如果在Hashset中,说明有环:如果不在Hashset中,将节点的ID存入Hashset. 这种方法时间复杂度已经最优,但是因为额外申请了Hashset,所以空间复杂度不算最优. 方法2:设置2个指针,指向头节点.第1个指针每次指向下一个节点:第2个指针指向下一个节点的下一