HDOJ2448-最短路,KM匹配

#include <cstdio>
#include <cstring>
#include <queue>
#include <iostream>
using namespace std;

const int NN=120;
const int INF=0x3fffffff;

struct node{
    int v,w;
    node() {}
    node(int _v,int _w): v(_v),w(_w) {}
};

int n,m,lx[NN],ly[NN],w[NN][NN],a[NN][NN],match[NN],slack[NN];
bool vx[NN],vy[NN];
bool dfs(int u)
{
    vx[u]=true;
    for (int v=0; v<m; v++)
    {
        if (vy[v]) continue;
        int t=lx[u]+ly[v]-w[u][v];
        if (t==0)
        {
            vy[v]=true;
            if (match[v]==-1 || dfs(match[v]))
            {
                match[v]=u;
                return true;
            }
        }
        else if (slack[v]>t) slack[v]=t;
    }
    return false;
}
int KM()
{
    memset(match,-1,sizeof(match));
    memset(lx,0,sizeof(lx));
    memset(ly,0,sizeof(ly));

    for (int i=0; i<n; i++)
        for (int j=0; j<m; j++) if (w[i][j]>lx[i]) lx[i]=w[i][j];

    for (int x=0; x<n; x++)
    {
        for (int i=0; i<m; i++) slack[i]=INF;

        while (1)
        {
            memset(vx,0,sizeof(vx));
            memset(vy,0,sizeof(vy));

            if (dfs(x)) break;

            int d=INF;
            for (int i=0; i<m; i++)
                if (!vy[i] && d>slack[i]) d=slack[i];

            for (int i=0; i<n; i++) if (vx[i]) lx[i]-=d;
            for (int i=0; i<m; i++) if (vy[i]) ly[i]+=d; else slack[i]-=d;

        }
    }

    int ret=0;
    for (int i=0; i<m; i++)
        if (match[i]!=-1) ret+=w[match[i]][i];

    printf("%d\n",-ret);
}

bool vis[320];
int dis[320][320];
vector<node> adj[320];
void spfa(int S,int *d)
{
    int i,u,v,size;
    for (i=1; i<=m+n; i++) d[i]=INF;
    d[S]=0;
    queue<int> q;
    q.push(S);

    while (!q.empty())
    {
        u=q.front();
        q.pop();
        vis[u]=false;
        size=adj[u].size();
        for (i=0; i<size; i++)
        {
            v=adj[u][i].v;
            if (d[v]>d[u]+adj[u][i].w)
            {
                d[v]=d[u]+adj[u][i].w;
                if (!vis[v])
                {
                    q.push(v);
                    vis[v]=true;
                }
            }
        }
    }
}

int at[NN];
int main()
{
    int k,p,a,b,c;
    while (~scanf("%d%d%d%d",&n,&m,&k,&p))
    {
        for (int i=1; i<=n; i++) scanf("%d",&at[i]);
        for (int i=1; i<=n+m; i++) adj[i].clear();
        for (int i=1; i<=k; i++)
        {
            scanf("%d%d%d",&a,&b,&c);
            adj[a].push_back(node(b,c));
            adj[b].push_back(node(a,c));
        }
        for (int i=1; i<=p; i++)
        {
            scanf("%d%d%d",&a,&b,&c);
            a+=m;
            adj[a].push_back(node(b,c));
            //adj[b].push_back(node(a,c)); //WA在這兒了
        }
        for (int i=1; i<=n; i++) spfa(i+m,dis[i]);
        for (int i=1; i<=n; i++)
            for (int j=1; j<=n; j++) w[i-1][j-1]=-dis[i][at[j]];
        m=n;
        KM();
    }
    return 0;
}

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