HDU 3435 A new Graph Game

題意:刪除一些邊得到一個或多個哈密爾頓圖,使得所有邊權之和最小

分析:雙向邊賦值,取反求最大匹配並判斷是否是完全匹配


#include <iostream>
#include<cstdio>
#include<string>
#include<algorithm>
#include<cstring>
#include<queue>
#define INF 60001
#define N 1005
using namespace std;
int nx,ny,lx[N],ly[N],link[N],slack[N],visx[N],visy[N],w[N][N];
bool DFS(int x){
    int y;
    visx[x]=1;
    for(y=1;y<=ny;y++){
        if(!visy[y]){
            int t=lx[x]+ly[y]-w[x][y];
            if(t==0){
                visy[y]=1;
                if(link[y]==-1||DFS(link[y])){
                    link[y]=x;
                    return true;
                }
            }else if(slack[y]>t){
                slack[y]=t;
            }
        }
    }
    return false;
}
int KM(){
    int i,j,x;
    memset(link,-1,sizeof(link));
    memset(ly,0,sizeof(ly));
    for(i=1;i<=nx;i++){
        for(j=1,lx[i]=-INF;j<=ny;j++)
        if(w[i][j]>lx[i])
        lx[i]=w[i][j];
    }
    for(x=1;x<=nx;x++){
        for(i=1;i<=ny;i++)
        slack[i]=INF;
        while(1){
            memset(visx,0,sizeof(visx));
            memset(visy,0,sizeof(visy));
            if(DFS(x))
            break;
            int d=INF;
            for(i=1;i<=ny;i++)
                if(!visy[i]&&d>slack[i])
                d=slack[i];
            for(i=1;i<=nx;i++)
                if(visx[i])
                lx[i]-=d;
            for(i=1;i<=ny;i++){
                if(visy[i])
                ly[i]+=d;
                else
                slack[i]-=d;
            }
        }
    }
    int ans=0;
    for(i=1;i<=ny;i++){
       if(link[i]==-1||w[link[i]][i]==-INF)
            return -1;
            ans+=w[link[i]][i];
    }
    return -ans;
}
int main()
{
    int T,s,t,i,j,k,ans,n,m,ics=0;
    scanf("%d",&T);
    while(T--){
        scanf("%d%d",&n,&m);
        nx=ny=n;
        for(i=1;i<=n;i++){
            for(j=1;j<=n;j++)
            w[i][j]=-INF;
        }
        while(m--){
            scanf("%d%d%d",&i,&j,&k);
            w[i][j]=max(w[i][j],-k);
            w[j][i]=w[i][j];
        }
        ans=KM();
        printf("Case %d: ",++ics);
        if(ans==-1)
        printf("NO\n");
        else
        printf("%d\n",ans);
    }
    return 0;
}


發佈了104 篇原創文章 · 獲贊 3 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章