1076. Trash

http://acm.timus.ru/problem.aspx?space=1&num=1076

图论题 关键在于建图 然后就是对模版的熟练运用

KM 最大匹配 此题是求最小匹配 只要把值变成负的 最后把结果再取一次负 就可以了

代码:

#include<iostream>

#include<cstdio>

#include<cstring>

#include<string>

#include<map>

#include<vector>

#include<stack>

#include<set>

#include<map>

#include<queue>

#include<algorithm>

#include<cmath>

#define LL long long

using namespace std;



const int N=155;

const int INF=0x3f3f3f3f;

//typedef pair<int,int>point;

int c[N][N];

int sum[N];

int dist[N][N];

int f[N];

bool lv[N],rv[N];

int a[N],b[N];

bool dfs(int x,int n)

{

    lv[x]=true;

    for(int i=1;i<=n;++i)

    {

        if(!rv[i]&&a[x]+b[i]==dist[x][i])

        {

            rv[i]=true;

            if(f[i]==-1||dfs(f[i],n))

            {

                f[i]=x;

                return true;

            }

        }

    }

    return false;

}



int Km(int n)

{

    memset(f,-1,sizeof(f));

    memset(b,0,sizeof(b));

    for(int i=1;i<=n;++i)

    {

        a[i]=-INF;

        for(int j=1;j<=n;++j)

        a[i]=max(a[i],dist[i][j]);

    }

    for(int l=1;l<=n;++l)

    {

        while(true)

        {

            memset(lv,false,sizeof(lv));

            memset(rv,false,sizeof(rv));

            if(dfs(l,n))

            break;

            int d=INF;

            for(int i=1;i<=n;++i)

            {

                if(lv[i])

                for(int j=1;j<=n;++j)

                {

                    if(!rv[j])

                    d=min(d,a[i]+b[j]-dist[i][j]);

                }

            }

            for(int i=1;i<=n;++i)

            {

                if(lv[i])

                a[i]-=d;

                if(rv[i])

                b[i]+=d;

            }

        }

    }

    int ans=0;

    for(int i=1;i<=n;++i)

    {

        if(f[i]!=-1)

        ans+=dist[f[i]][i];

    }

    return ans;

}

int main()

{

    int n;

    while(cin>>n)

    {

        memset(sum,0,sizeof(sum));

        for(int i=1;i<=n;++i)

        {

            for(int j=1;j<=n;++j)

            {

                cin>>c[i][j];

                sum[j]+=c[i][j];

            }

        }

        memset(dist,0,sizeof(dist));

        for(int i=1;i<=n;++i)

        {

            for(int j=1;j<=n;++j)

            {

                int tmp=sum[j]-c[i][j];

                dist[j][i]=-tmp;

            }

        }

        cout<<(-Km(n))<<endl;

    }

    return 0;

}

  

你可能感兴趣的:(sh)