• HDU4009 Transfer water [最小树形图]


      最小树形图模版题,学习了一下最小树形图。

      三步走,找最小入弧,找有向环,缩环为点。

    #include <string.h>
    #include <stdio.h>
    #include <stdlib.h>
    #define INF 0x3f3f3f3f
    #define MAXN 1001
    struct edge{
        int u,v,w;
    }e[MAXN*MAXN];
    int n,x,y,z,es,k,tt;
    int pnt[MAXN][3];
    int dist(int p1,int p2){
        int ret=0;
        for(int i=0;i<3;i++)ret+=abs(pnt[p1][i]-pnt[p2][i]);
        return ret;
    }
    void addedge(int u,int v,int w){
        e[es].u=u,e[es].v=v,e[es].w=w,es++;
    }
    /*点和边都是从0开始的,root包含在点集中*/
    int in[MAXN],pre[MAXN],id[MAXN],vis[MAXN];
    int dir_mst(int root,int vs,int es){
        int ret=0;
        for(;;){
            int size=vs*4;
            memset(in,0x3f,size);
            memset(id,-1,size);
            memset(vis,-1,size);
            //step1:找最小入弧
            for(int i=0;i<es;i++){
                int u=e[i].u,v=e[i].v,w=e[i].w;
                if(w>=in[v]||u==v)continue;
                pre[v]=u,in[v]=w;
            }
            in[root]=0,pre[root]=root;
                //如果有孤立点说明无解
            for(int i=0;i<vs;i++){
                ret+=in[i];
                if(in[i]==INF)return -1;
            }
            //step2:找有向环
            int idx=0;
            for(int i=0;i<vs;i++)if(vis[i]==-1){
                int u=i;
                while(vis[u]==-1)vis[u]=i,u=pre[u];
                if(vis[u]!=i||u==root)continue;
                for(int t=pre[u];t!=u;t=pre[t])id[t]=idx;
                id[u]=idx++;
            }
                //没有环,已经完成
            if(idx==0)break;
            for(int i=0;i<vs;i++)if(id[i]==-1)id[i]=idx++;
            //step3:将环缩为点
            for(int i=0;i<es;i++){
                e[i].w-=in[e[i].v];
                e[i].u=id[e[i].u];
                e[i].v=id[e[i].v];
            }
            vs=idx;
            root=id[root];
        }
        return ret;
    }
    int main(){
        freopen("test.in","r",stdin);
        while(scanf("%d%d%d%d",&n,&x,&y,&z),n||x||y||z){
            for(int i=1;i<=n;i++)
                scanf("%d%d%d",&pnt[i][0],&pnt[i][1],&pnt[i][2]);
            es=0;
            for(int i=1;i<=n;i++)
                addedge(0,i,pnt[i][2]*x);
            for(int i=1;i<=n;i++){
                scanf("%d",&k);
                while(k--){
                    scanf("%d",&tt);
                    if(pnt[i][2]>=pnt[tt][2])addedge(i,tt,dist(i,tt)*y);
                    else addedge(i,tt,dist(i,tt)*y+z);
                }
            }
            int res=dir_mst(0,n+1,es);
            if(res==-1)printf("poor XiaoA\n");
            else printf("%d\n",res);
        }
    }
  • 相关阅读:
    linux下,webpack热重载无效的解决方法
    前端异步编程之Promise和async的用法
    防呆设计(内容摘录)
    GUI 图形用户界面 [学习笔记]
    15条JavaScript最佳实践【转】
    2013-11-02 【webrebuild广州站】分享会纪要
    关于自控力
    记录一次抖音小程序严重bug(组件样式继承问题)
    微信 头条小程序 记录一次电商项目倒计时活动优化
    微信/头条小程序如何确保异步请求执行完后再执行各页面的onLoad方法
  • 原文地址:https://www.cnblogs.com/swm8023/p/2659264.html
Copyright © 2020-2023  润新知