1. 程式人生 > >HDU 6141 I am your Father!(最小樹形圖)

HDU 6141 I am your Father!(最小樹形圖)

truct 操作 div blog 直接 .cn clu lld 最小樹形圖

【題目鏈接】 http://acm.hdu.edu.cn/showproblem.php?pid=6141

【題目大意】

  給出一個有向圖,求1點為根的最小樹形圖使得第n個點的直接父親編號最小

【題解】

  如果沒有第n個點直接父親編號最小的要求,
  那麽只要跑一遍朱劉算法即可,考慮到直接父親最小的條件,
  我們連向第n個點的所有邊進行加權操作,
  使得其在總邊權相同的情況選取答案具有優先性

【代碼】

#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long LL; 
const int N=1010,M=10010;
const LL INF=0x3f3f3f3f3f3f3f3f;
int ROOT;
struct DMST{
    int n,size,pre[N],id[N],vis[N];
    LL in[N];
    struct EDGE{
        int u,v; LL cost;
        EDGE(){}
        EDGE(int a,int b,int c):u(a),v(b),cost(c){}
    }E[M];
    void init(int _n){n=_n,size=0;}
    void add(int u,int v,int w){E[size++]=EDGE(u,v,w);}
    LL dmst(int root){
        int u,v,cnt;
        LL ret=0;
        while(1){
            for(int i=0;i<n;i++)in[i]=INF;
            for(int i=0;i<size;i++){
                u=E[i].u,v=E[i].v;
                if(E[i].cost<in[v]&&u!=v){
                    pre[v]=u,in[v]=E[i].cost;
                    if(u==root)ROOT=i;
                }
            }
            for(int i=0;i<n;i++)if(i!=root&&in[i]==INF)return -1;
            cnt=in[root]=0;
            for(int i=0;i<n;i++)id[i]=vis[i]=-1;
            for(int i=0;i<n;i++){
                ret+=in[i],v=i;
                while(vis[v]!=i&&id[v]==-1&&v!=root)vis[v]=i,v=pre[v];
                if(v!=root&&id[v]==-1){
                    for(u=pre[v];u!=v;u=pre[u])id[u]=cnt;
                    id[v]=cnt++;
                }
            }
            if(!cnt)break;
            for(int i=0;i<n;i++)if(id[i]==-1)id[i]=cnt++;
            for(int i=0;v=E[i].v,i<size;i++){
                E[i].u=id[E[i].u],E[i].v=id[E[i].v];
                if(E[i].u!=E[i].v)E[i].cost-=in[v];
            }n=cnt,root=id[root];
        }return ret;
    }
}U;
int T,n,m;
int main(){
    scanf("%d",&T);
    while(T--){
        scanf("%d%d",&n,&m);
        U.init(n);
        while(m--){
            int x,y,z;
            scanf("%d%d%d",&x,&y,&z);
            z*=1000; if(y==n)z+=n-x;
            U.add(x-1,y-1,-z);
        }LL ans=-U.dmst(0);
        int fa=n-ans%1000;
        ans/=1000;
        printf("%lld %d\n",ans,fa);
    }return 0;
}

HDU 6141 I am your Father!(最小樹形圖)