51nod 1640 天气晴朗的魔法 prime队列+最小生成树+最大生成树+邻接表

题目:

51nod魔法学校近日开展了主题为“天气晴朗”的魔法交流活动。

N名魔法师按阵法站好,之后选取N - 1条魔法链将所有魔法师的魔力连接起来,形成一个魔法阵。

魔法链是做法成功与否的关键。每一条魔法链都有一个魔力值V,魔法最终的效果取决于阵中所有魔法链的魔力值的和。

由于逆天改命的魔法过于暴力,所以我们要求阵中的魔法链的魔力值最大值尽可能的小,与此同时,魔力值之和要尽可能的大。

现在给定魔法师人数N,魔法链数目M。求此魔法阵的最大效果。
Input
两个正整数N,M。(1 <= N <= 10^5, N <= M <= 2 * 10^5)

接下来M行,每一行有三个整数A, B, V。(1 <= A, B <= N, INT_MIN <= V <= INT_MAX)

保证输入数据合法。
Output
输出一个正整数R,表示符合条件的魔法阵的魔力值之和。
Input示例
4 6
1 2 3
1 3 1
1 4 7
2 3 4
2 4 5
3 4 6
Output示例
12


思路:首先因为要找到生成树里面魔力值的最大值的最小值,所以可以用最小生成树跑一边,求出两个节点距离最大的点,这就是最大的了。然后用最小生成树的算法跑一边最大生成树,权值不能大于前面求出的那个值。


#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <map>
#include <set>
#include <iomanip>

using namespace std;
#define maxn 2000005
#define MOD 1000000007
#define mem(a , b) memset(a , b , sizeof(a))
#define LL long long
#define INF 1000000000

typedef struct
{
    int v;
    int next;
    int cost;
}Edge;

typedef struct
{
    int v;
    int cost;
}node;

typedef struct
{
    int v;
    int cost;
}Node;
bool operator <(const node &a,const node &b)
{
    return a.cost>b.cost;
}

bool operator <(const Node &a,const Node &b)
{
    return a.cost<b.cost;
}

priority_queue<node> q;
priority_queue<Node> q2;

const long MAXN=100005;
Edge e[4*MAXN];
int p[MAXN];
bool vist[MAXN];

int m,n;
int from,to,cost;

void init()
{
    memset(p,-1,sizeof(p));
    memset(vist,0,sizeof(vist));

    while (!q.empty())
    {
        q.pop();
    }

    int i;
    int eid=0;
    for (i=0;i<m;++i)
    {
        scanf("%d %d %d",&from,&to,&cost);
        e[eid].next=p[from];
        e[eid].v=to;
        e[eid].cost=cost;
        p[from]=eid++;

        //以下适用于无向图

        swap(from,to);

        e[eid].next=p[from];
        e[eid].v=to;
        e[eid].cost=cost;
        p[from]=eid++;

    }
}


int Prime()
{
    LL cost=0;
    node t;
    t.v=from;//选择起点
    t.cost=0;

    q.push(t);
    int minn = -99999999;

    LL tt=0;

    while (!q.empty()&&tt<m)
    {
        t=q.top();
        q.pop();

        if (vist[t.v] )
        {
            continue;
        }

        cost+=t.cost;
        minn = max(t.cost , minn);
        ++tt;

        vist[t.v]=true;

        int j;
        for (j=p[t.v];j!=-1;j=e[j].next)
        {
            if (!vist[e[j].v] )
            {
                node temp;
                temp.v=e[j].v;
                temp.cost=e[j].cost;
                q.push(temp);
            }
        }
    }
    return minn;
}

void prime2(int minn)
{
    LL cost=0;
    Node t;
    t.v=from;//选择起点
    t.cost=0;
    mem(vist , 0);
    while(!q2.empty()) q2.pop();
    q2.push(t);

    LL tt=0;

    while (!q2.empty()&&tt<m)
    {
        t=q2.top();
        q2.pop();

        if (vist[t.v] )
        {
            continue;
        }

        cost+=t.cost;
        ++tt;

        vist[t.v]=true;

        int j;
        for (j=p[t.v];j!=-1;j=e[j].next)
        {
            if (!vist[e[j].v] && e[j].cost <= minn)
            {
                Node temp;
                temp.v=e[j].v;
                temp.cost=e[j].cost;
                q2.push(temp);
            }
        }
    }
    printf("%lld\n" , cost);
}

int main()
{
    while (scanf("%d %d",&n,&m)!=EOF)
    {
        init();
        int minn = Prime();
       // cout << minn << endl;
        prime2(minn);
    }
    return 0;
}

超时代码:


#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <map>
#include <set>
#include <iomanip>

using namespace std;
#define maxn 2000005
#define MOD 1000000007
#define mem(a , b) memset(a , b , sizeof(a))
#define LL long long
#define INF 1000000000

struct node
{
    int u , v , w;
    bool friend operator<(node n1 , node n2)
    {
        return n1.w < n2.w;
    }
}a[maxn];

int vis[maxn];
vector<node>s;
vector<node>::iterator it;
int n , m;

template <class T>
inline bool scan_d(T &ret)
{
    char c; int sgn;
    if (c = getchar(), c == EOF) return 0; //EOF
    while (c != '-' && (c<'0' || c>'9')) c = getchar();
    sgn = (c == '-') ? -1 : 1;
    ret = (c == '-') ? 0 : (c - '0');
    while (c = getchar(), c >= '0'&&c <= '9') ret = ret * 10 + (c - '0');
    ret *= sgn;
    return 1;
}

bool cmp(node n1 , node n2)
{
    return n1.w < n2.w;
}

int main()
{
    while(scanf("%d %d" , &n , &m) != EOF)
    {
        s.clear();
        mem(vis , 0);
        for(int i = 0; i < m ; i ++)
        {
            scanf("%d %d %d" , &a[i].u , &a[i].v , &a[i].w);
           // s.insert(a[i]);
           s.push_back(a[i]);
        }
        sort(s.begin() , s.end() , cmp) ;
        int minn = - 999999999;
        int num = 0;
        it = s.begin();
        vis[it->u] = 1;
       // cout << it -> u << endl;
        for(int i = 0 ; i < n - 1 ; i ++)
        {
            for( it = s.begin() ; it != s.end() ; it++)
            {
                if((vis[it->u] && !vis[it -> v]) || (vis[it->v] && ! vis[it->u])) break;
            }
            vis[it->u] = 1;
            vis[it->v] = 1;
            minn = max(minn , it -> w);
            s.erase(it);
        }
       // cout << minn << endl;
        s.clear();
        for(int i = 0 ; i < m ; i ++) if(a[i].w <= minn) s.push_back(a[i]);
        sort(s.begin() , s.end() , cmp) ;
        LL ans = 0;
        mem(vis ,0);
        it = s.end();
        it --;
        vis[it->u] = 1;
        for(int i = 0 ; i < n - 1 ; i ++)
        {
            for( it = --(s.end()) ;  ; it--)
            {
                if((vis[it->u] && !vis[it -> v]) || (vis[it->v] && ! vis[it->u])|| it == s.begin()) break;
            }
            vis[it->u] = 1;
            vis[it->v] = 1;
            ans += it -> w;
            s.erase(it);
        }
        printf("%lld\n" , ans);
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值