您的位置:首页 > 其它

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

2015-08-25 20:55 453 查看

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
HintIn 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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: