模板-KM算法

来源:互联网 发布:linux如何查看内核日志 编辑:程序博客网 时间:2024/06/01 13:39
#include <bits/stdc++.h>using namespace std;const int maxn = 66;const int maxN = 410;int lx[maxN];int ly[maxN];int sx[maxN];int sy[maxN];int match[maxN];int weight[maxN][maxN];int sz;bool path(int u){    sx[u] = true;    for(int v=1;v<=sz;v++){        if(!sy[v] && lx[u] + ly[v] == weight[u][v]){            sy[v] = true;            if(match[v] == -1 || path(match[v])){                match[v] = u;                return true;            }        }    }    return false;}int bestmatch(){    int i,j;    for(i=1;i<=sz;i++){        lx[i] = 0x80000000;        ly[i] = 0;        for(j=1;j<=sz;j++){            if(lx[i]<weight[i][j]){                lx[i] = weight[i][j];            }        }    }    memset(match,-1,sizeof(match));    for(int u=1;u<=sz;u++){        while(1){            memset(sx,0,sizeof(sx));            memset(sy,0,sizeof(sy));            if(path(u)){                break;            }            int dx = 0x7fffffff;            for(i=1;i<=sz;i++){                if(sx[i]){                    for(j=1;j<=sz;j++){                        if(!sy[j]){                            dx = min(lx[i]+ly[j]-weight[i][j],dx);                        }                    }                }            }            for(i=1;i<=sz;i++){                if(sx[i]){                    lx[i] -= dx;                }                if(sy[i]){                    ly[i] += dx;                }            }        }    }    int sum = 0;    for(i=1;i<=sz;i++){        sum+=weight[match[i]][i];    }    return sum;}vector<int> adj[maxn];int height[maxn];int p[maxn];int pEdge[maxn];struct Edge{    int u;    int v;    int w;    Edge(int u,int v,int w):u(u),v(v),w(w){    }    Edge(){    }}edges[maxN];void predfs(int u){    for(int i=0;i<adj[u].size();i++){        int v = edges[adj[u][i]].u;        if(v==u){            v = edges[adj[u][i]].v;        }        if(v!=p[u]){            p[v] = u;            pEdge[v] = adj[u][i];            height[v] = height[u] + 1;            predfs(v);        }    }}void init(){    memset(weight,0,sizeof(weight));    memset(adj,0,sizeof(adj));    memset(p,0,sizeof(p));}void addedge(int u,int v,int id){    adj[u].push_back(id);    adj[v].push_back(id);}int uu[maxN];int vv[maxN];int ww[maxN];int main(){    int t;    cin>>t;    while(t--){        init();        int n,m;        cin>>n>>m;        for(int i=1;i<=m;i++){            cin>>uu[i]>>vv[i]>>ww[i];            if(i<n){                edges[i] = Edge(uu[i],vv[i],ww[i]);                addedge(uu[i],vv[i],i);            }else{            }        }        predfs(1);        int szX = n-1;        int szY = m-n+1;        sz = max(szX,szY);        int Yid = 1;        for(int i=n;i<=m;i++){            int u = uu[i];            int v = vv[i];            if(height[u]>height[v]){                swap(u,v);            }            int Xid;            int sum;            // move v            while(height[v] > height[u]){                Xid = pEdge[v];                sum = ww[Xid] - ww[i];                if(sum<0){                    sum = 0;                }                weight[Xid][Yid] = sum;                v = p[v];            }            //move u and v            while(u!=v){                Xid = pEdge[u];                sum = ww[Xid] - ww[i];                if(sum<0){                    sum = 0;                }                weight[Xid][Yid] = sum;                Xid = pEdge[v];                sum = ww[Xid] - ww[i];                if(sum<0){                    sum = 0;                }                weight[Xid][Yid] = sum;                u = p[u];                v = p[v];            }            Yid++;        }/*        for(int i=1;i<=sz;i++){            for(int j=1;j<=sz;j++){                cout<<weight[i][j]<<" ";            }            cout<<endl;        }*/        bestmatch();        for(int i=1;i<=szX;i++){            cout<<ww[i] - lx[i]<<endl;        }        for(int i=1;i<=szY;i++){            cout<<ww[i+n-1] + ly[i]<<endl;        }    }    return 0;}
0 0