zoukankan      html  css  js  c++  java
  • HDU 1853 Cyclic Tour

    HDU_1853

    首先,如果要保证图有环,并且环之间没有交点的话,那么必然每个点的出度和入度都应为1,因此我们可以把一个点拆成两个点,分别表示出度及入度,然后去找拆点后构成的二分图的完美匹配。

    对于怎么判断原图是否能构成完美匹配,我暂时想到了两个思路:

    ①在用KM算法之前先用匈牙利算法求最大匹配,如果最大匹配数为N,那么就一定会存在完美匹配。

    ②我们可以从KM算法的slack变量入手,每一次更新slack,都是在尝试进行新一轮的增广,并且会把更多的原本不在交错树中的点加入进来,当把所有可以加到交错树中点都加入之后,slack就不会再进行更新。换句话讲,如果slack不再更新,那么一定是把所有可以加到交错树中的点都已经加入了,并且这个时候依然不能找到增广路。因此,当slack不再更新的时候我们就可以断定原图不能构成完美匹配了。当然这么做的前提是,我们需要把slack放到for(;;)的里面去,并且每次尝试增广之前,都初始化成INF

    #include<stdio.h>
    #include<string.h>
    #define MAXD 110
    #define INF 1000000000
    #define MAX 1001
    int yM[MAXD], visy[MAXD], visx[MAXD];
    int G[MAXD][MAXD], N, M, A[MAXD], B[MAXD], slack;
    void init()
    {
    int i, a, b, temp;
    memset(G, 0, sizeof(G));
    for(i = 0; i < M; i ++)
    {
    scanf("%d%d%d", &a, &b, &temp);
    a --;
    b --;
    if(!G[a][b] || MAX - temp > G[a][b])
    G[a][b] = MAX - temp;
    }
    }
    int searchpath(int u)
    {
    int v, temp;
    visx[u] = 1;
    for(v = 0; v < N; v ++)
    if(G[u][v] && !visy[v])
    {
    temp = A[u] + B[v] - G[u][v];
    if(temp == 0)
    {
    visy[v] = 1;
    if(yM[v] == -1 || searchpath(yM[v]))
    {
    yM[v] = u;
    return 1;
    }
    }
    else if(temp < slack)
    slack = temp;
    }
    return 0;
    }
    int EK()
    {
    int i, j;
    for(i = 0; i < N; i ++)
    {
    A[i] = 0;
    for(j = 0; j < N; j ++)
    if(G[i][j] && G[i][j] > A[i])
    A[i] = G[i][j];
    }
    memset(B, 0, sizeof(B));
    memset(yM, -1, sizeof(yM));
    for(i = 0; i < N; i ++)
    {
    for(;;)
    {
    slack = INF;
    memset(visx, 0, sizeof(visx));
    memset(visy, 0, sizeof(visy));
    if(searchpath(i))
    break;
    if(slack == INF)
    return 0;
    for(j = 0; j < N; j ++)
    {
    if(visx[j])
    A[j] -= slack;
    if(visy[j])
    B[j] += slack;
    }
    }
    }
    return 1;
    }
    void printresult()
    {
    int i, res = 0;
    for(i = 0; i < N; i ++)
    res += MAX - G[yM[i]][i];
    printf("%d\n", res);
    }
    int main()
    {
    int i, j;
    while(scanf("%d%d", &N, &M) != EOF)
    {
    init();
    if(EK())
    printresult();
    else
    printf("-1\n");
    }
    return 0;
    }



  • 相关阅读:
    SQL2005 SQL2008 远程连接配置方法
    Subvision 安装 部署 TortoiseSVN
    在wpf或winform关闭子窗口或对子窗口进行某个操作后刷新父窗口
    C# 中的委托和事件
    长数字隔三位用逗号","隔开,保留两位小数,指定长度,不足补空格
    C# 柱状图, 折线图, 扇形图
    如何在Visual Studio 2010旗舰版本下安装Window Phone 7 简体中文开发环境
    vs2010发布、打包安装程序(超全超详细)
    java 环境搭建
    SQL2008 转 2000(高版本转换到低版本)
  • 原文地址:https://www.cnblogs.com/staginner/p/2199064.html
Copyright © 2011-2022 走看看