• poj 3723 Conscription(Kruskal + 并查集)


    题意:windy要组建一支军队,召集了N个女孩和M个男孩,每个人要付10000RMB,但是如果一个女孩和一个男孩有关系d的,且已经付给了其中一个人的钱,那么就可以付给另一个人10000-d元,求windy最少要付多少钱。

    解题过程:写了一个prim的最小生成树才发现原来整个图不是连通的,所以想到用Kruskal,刚开始的时候val中存的是10000-d,然后求最小生成树,但是最后求有几棵树的时候不是很好计算,改了一下f[x]、f[y]的赋值规则还是不行,然后看到有人说求最大生成树,然后就改了一下条件就AC了。

    代码:

    View Code
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <iostream>
    #include <algorithm>
    #include <queue>
    #include <math.h>
    #define  N 50005
    #define  M 20005
    using namespace std ;
    
    struct node
    {
        int s , e ;
        int val ;
    }p[N] ;
    
    int f[M] , n , m , r , num ;
    
    int cmp ( const node a , const node b )
    {
        return a.val > b.val ;
    }
    
    void init()
    {
        int i ;
        for ( i = 0 ; i <=  n + m ; i++ )
        f[i] = i ;
    }
    
    void add ( int x , int y , int z )
    {
        p[num].s = x ;
        p[num].e = y ;
        p[num].val = z ;
        num++ ;
    }
    
    int find ( int x )
    {
        if ( f[x] != x )
        f[x] = find ( f[x] ) ;
        return f[x] ;
    }
    
    int main()
    {
        int cas , i , x , y , z ;
    
        //freopen( "input.txt" , "r" , stdin) ;
        scanf ( "%d" , &cas ) ;
        while ( cas-- )
        {
            scanf ( "%d%d%d" , &n , &m , &r ) ;
            num = 0 ;
            for ( i = 1 ; i <= r ; i++ )
            {
                scanf ( "%d%d%d" , &x , &y , &z ) ;
                add ( x + 1 , y + n + 1 , z );
            }
    
            sort ( p , p + num , cmp ) ;
            init() ;
            int sum = ( n + m ) * 10000 ;
            for ( i = 0 ; i < num ; i++ )
            {
                x = find ( p[i].s ) ;
                y = find ( p[i].e ) ;
                if ( x != y )
                {
                    sum -= p[i].val ;
                    f[x] = y ;
                }
            }
            for ( i = 1 ; i <= n + m ; i++ )
            cout<<f[i]<<" ";
            cout<<endl ;
    
            /*sort ( f , f + n + m + 1 ) ;
            x = 1 ;
            for ( i = 2 ; i <= n + m ; i++ )
            if ( f[i] != f[i-1] )
            x++ ;*/
    
            printf ( "%d\n" , sum ) ;
        }
        return 0 ;
    }
  • 相关阅读:
    Spring3整合Quartz实现定时作业
    伪静态URLRewrite学习笔记
    VC 获取系统特殊文件夹的路径如:系统目录,桌面等
    正反向代理
    过虚拟机检测
    PDB符号文件信息
    Win64 驱动内核编程-33.枚举与删除对象回调
    Windows 反调试技术——OpenProcess 权限过滤
    Win10如何开启蓝屏记录?Win10开启蓝屏信息记录的方法
    Win7 x64下进程保护与文件保护(ObRegisterCallbacks)
  • 原文地址:https://www.cnblogs.com/misty1/p/2739066.html
Copyright © 2020-2023  润新知