HDU 3435 A new Graph Game

来源:互联网 发布:qq飞车终极麦凯伦数据 编辑:程序博客网 时间:2024/04/29 14:15

HDU 3435 A new Graph Game

题目链接:HDU 3435



题意:

找出一条费用最小的圈并且每个点走一次

分析:

最小权完备匹配


#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>using namespace std;const int maxn=1005;const int INF=1e9;int g[maxn][maxn];bool visitx[maxn], visity[maxn];int lx[maxn], ly[maxn];int slack[maxn];int match[maxn];int n,m;bool Hungary(int u) //匈牙利算法{    visitx[u] = true;    for(int i = 1; i <= n; ++i)    {        if(visity[i])            continue;        if(lx[u] + ly[i] == g[u][i])        {            visity[i] = true;            if(match[i] == -1 || Hungary(match[i]))            {                match[i] = u;                return true;            }        }        else //不在相等子图            slack[i] = min(slack[i], lx[u] + ly[i] - g[u][i]);    }    return false;}void KM(){    int temp;memset(match, -1, sizeof(match));    memset(lx, 0, sizeof(lx)); //初始化顶标    memset(ly, 0, sizeof(ly)); //ly[i]为0    for(int i = 1; i <= n; ++i) //lx[i]为权值最大的边        for(int j = 0; j <= m; ++j)            lx[i] = max(lx[i], g[i][j]);    for(int i = 1; i <= n; i++) //对n个点匹配    {        for(int j = 1; j <= n; j++)            slack[j] = INF;        while(1)        {            memset(visitx, false, sizeof(visitx));            memset(visity, false, sizeof(visity));            if(Hungary(i)) //匹配成功                break;            else //匹配失败,找最小值            {                temp = INF;                for(int j = 1; j <= n; j++)                    if(!visity[j])                        if(temp > slack[j])                            temp = slack[j];                for(int j = 1; j <= n; j++) //更新顶标                {                    if(visitx[j])                        lx[j] -= temp;                }                for(int j=1;j<=m;++j)                {                   if(visity[j])                        ly[j] += temp;                   else                        slack[j] -= temp;                }            }        }    }int ans = 0,flag=0;    for(int i = 1; i <= m; i++) //权值相加{if(match[i]==-1|| g[match[i]][i] == -INF){flag=1;break;}        ans += g[match[i]][i];}if(flag)printf("NO\n");else   printf("%d\n", -ans);}int main(){// freopen("in.txt","r",stdin);int a,b,c;int T,Case=1;scanf("%d",&T);while(T--){scanf("%d %d", &n,&m);for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)g[i][j]=-INF;for(int i=0;i<m;i++){scanf("%d %d %d",&a,&b,&c);if(-c>g[a][b])g[a][b]=g[b][a]=-c;}m=n;printf("Case %d: ",Case++);KM();    }    return 0;}


0 0