最小树形图(朱刘算法)学习笔记&板子

版权声明:...............转载说一声并注明出处qaq............... https://blog.csdn.net/L_0_Forever_LF/article/details/80961982

最小树形图朱刘算法
大概流程:
初始化答案ans=0
1.每个点v选个最小入边(u,v,prec[v]),如果有点没有prec就无解
2.i,irootans+=prec[i]
2.若最小入边构成的是一棵树,那这个就是答案
3.否则最小入边会构成一棵树和若干个环,建一个新图G,在新图中把环缩成一个点v
4.设点x在新图中对应点x,对于原图中的一条边(u,v,w),若他在新图中不是一个自环,建边(u,v,wprec[v]),然后回到步骤1

板子
hdu2121
code:

#include<set>
#include<map>
#include<deque>
#include<queue>
#include<stack>
#include<cmath>
#include<ctime>
#include<bitset>
#include<string>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<climits>
#include<complex>
#include<iostream>
#include<algorithm>
#define ll long long
#define pb push_back
#define SZ(x) (int)x.size()
#define mp make_pair
#define fir first
#define sec second
using namespace std;

const int maxn = 11000;
const int maxm = 11000;

ll ans,sum; int root;
int n,m;
struct node
{
    int ty,y; ll c;
    node(){}
    node(int _ty,int _y,ll _c){ty=_ty,y=_y,c=_c;}
};
vector<node>G[maxn],nG[maxn];
ll pc[maxn];
int pi[maxn],pv[maxn];

void init()
{
    ans=0,sum=0;
    for(int i=1;i<=n+1;i++) G[i].clear(),nG[i].clear(),pc[i]=LLONG_MAX,pv[i]=0,pi[i]=0;
}
int id[maxn],cnt;
int vis[maxn];
int solve(int rt)
{
    while(1)
    {
        for(int i=1;i<=n;i++) if(i!=rt&&!pv[i]) return 0;
        for(int i=1;i<=n;i++) ans+=pc[i];

        int cir=0; cnt=0;
        for(int i=1;i<=n;i++) vis[i]=0,id[i]=0;
        vis[rt]=-1;
        for(int i=1;i<=n;i++)
        {
            int u;
            for(u=i;!vis[u];u=pv[u]) vis[u]=i;
            if(vis[u]==i)
            {
                cir=1;
                id[u]=++cnt;
                for(int v=pv[u];v!=u;v=pv[v]) id[v]=cnt;
            }
        }
        for(int i=1;i<=n;i++) if(!id[i]) id[i]=++cnt;
        if(!cir)
        {
            for(int i=1;i<=n;i++) if(i!=rt&&pv[i]==rt) root=pi[i];
            return ans<2*sum;
        }

        for(int i=1;i<=cnt;i++) nG[i].clear();
        for(int i=1;i<=n;i++)
        {
            for(int j=0;j<SZ(G[i]);j++)
            {
                int y=G[i][j].y; ll c=G[i][j].c-pc[y];
                if(id[i]==id[y]) continue;
                nG[id[i]].pb(node(G[i][j].ty,id[y],c));
            }
        }
        n=cnt;
        for(int i=1;i<=n;i++) pc[i]=LLONG_MAX,pi[i]=pv[i]=0;
        for(int i=1;i<=n;i++)
        {
            G[i].clear();
            for(int j=0;j<SZ(nG[i]);j++)
            {
                G[i].pb(nG[i][j]);
                int y=G[i][j].y; ll c=G[i][j].c;
                if(c<pc[y]||(c==pc[y]&&G[i][j].ty<pi[y]))
                    pc[y]=c,pv[y]=i,pi[y]=G[i][j].ty;
            }
        }
        pc[rt=id[rt]]=0;
    }
}

int main()
{
    //freopen("tmp.in","r",stdin);
    //freopen("tmp.out","w",stdout);

    while(scanf("%d%d",&n,&m)!=EOF)
    {
        init();
        for(int i=1;i<=m;i++)
        {
            int x,y;ll c; scanf("%d%d%lld",&x,&y,&c);
            x++,y++;
            if(x==y) continue;
            G[x].pb(node(y,y,c));
            sum+=c;
            if(pc[y]>c) pc[y]=c,pv[y]=x,pi[y]=y;
        }
        sum++;
        for(int i=1;i<=n;i++)
        {
            G[n+1].pb(node(i,i,sum));
            if(pc[i]>sum) pc[i]=sum,pv[i]=n+1,pi[i]=i;
        }
        pc[++n]=0;
        if(!solve(n)) puts("impossible");
        else printf("%lld %d\n",ans-sum,root-1);
        putchar('\n');
    }

    return 0;
}
阅读更多
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页