hdu4966最小树形图

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#define REP(i,a,b) for(int i=a;i<=b;i++)
#define MS0(a) memset(a,0,sizeof(a))

using namespace std;

typedef long long ll;
const int maxn=1000100;
const int INF=1e9+10;

int n,m;
int a[52];
int c[2100],L1[2100],d[2100],L2[2100],money[2100];
int id[52][520];
int N;

/// D-MST
struct Edge
{
    int u,v,w;
};Edge e[maxn];int en;
int in[25100];
int pre[25100],ID[25100],vis[25100];

/// D-MST 点的标号必须是0~N-1,不能改成0~N或1~N
int D_MST(int rt,int n,int m)
{
    int res=0;
    while(1){
        REP(i,0,n-1) in[i]=INF;
        REP(i,1,m){
            int u=e[i].u,v=e[i].v,w=e[i].w;
            if(w<in[v]&&u!=v){
                pre[v]=u;
                in[v]=w;
            }
        }
        REP(i,0,n-1){
            if(i==rt) continue;
            if(in[i]==INF) return -1;
        }
        int cntnode=0;
        memset(ID,-1,sizeof(ID));
        memset(vis,-1,sizeof(vis));
        in[rt]=0;
        REP(i,0,n-1){
            res+=in[i];
            int v=i;
            while(vis[v]!=i&&ID[v]==-1&&v!=rt){
                vis[v]=i;
                v=pre[v];
            }
            if(v!=rt&&ID[v]==-1){
                for(int u=pre[v];u!=v;u=pre[u]) ID[u]=cntnode;
                ID[v]=cntnode++;
            }
        }
        if(cntnode==0) break;
        REP(i,0,n-1) if(ID[i]==-1) ID[i]=cntnode++;
        REP(i,1,m){
            int v=e[i].v;
            e[i].u=ID[e[i].u];
            e[i].v=ID[e[i].v];
            if(e[i].u!=e[i].v) e[i].w-=in[v];
        }
        n=cntnode;
        rt=ID[rt];
    }
    return res;
}
/// s=0,u=0~N-1 ; e=1~en
void build()
{
    N=1;
    REP(i,1,n) REP(j,0,a[i]) id[i][j]=N++;
    en=0;
    REP(i,1,n) e[++en]=(Edge){0,id[i][0],0};
    REP(i,1,m) e[++en]=(Edge){id[c[i]][L1[i]],id[d[i]][L2[i]],money[i]};
    REP(i,1,n) REP(j,1,a[i]) e[++en]=(Edge){id[i][j],id[i][j-1],0};
}

int solve()
{
    return D_MST(0,N,en);
}

int main()
{
    freopen("in.txt","r",stdin);
    while(cin>>n>>m,n||m){
        REP(i,1,n) scanf("%d",&a[i]);
        REP(i,1,m) scanf("%d%d%d%d%d",&c[i],&L1[i],&d[i],&L2[i],&money[i]);
        build();
        printf("%d\n",solve());
    }
    return 0;
}
View Code