Prim 的堆优化



#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <stack>
#include <cmath>
#include <vector>
#include <queue>
#include <map>
#include <set>
using namespace std;
#define LL long long
#define M 10010
#define DEBUG puts("It's here!")
#define INF 1<<29
#define CLS(x,v) memset(x,v,sizeof(x))
#define FOR(i,a,n)  for(int i=(a);i<=(n);++i)
#define filer freopen("C:\\Users\\sq\\Desktop\\data.in","r",stdin);
#define filew freopen("C:\\Users\\sq\\Desktop\\data.out","w",stdout);


struct Edge{
   int to,cost,len;
}e,dist[M];
int n;
vector<Edge> g[M];
bool vis[M];
struct cmp{
   bool operator()(const int &a,const int &b)const{
      if(dist[a].len==dist[b].len)
        return dist[a].cost!=dist[b].cost?dist[a].cost<dist[b].cost:a<b;
      return dist[a].len<dist[b].len;
   }
};
set<int,cmp> v;//存储各个点的标号
void prim(int s)
{
    for(int i=1;i<=n;i++)
        dist[i].cost=dist[i].len=INF;
    dist[s].cost=dist[s].len=0;
    CLS(vis,0);
    v.clear();
    v.insert(s);
    int k,cnt=0;
    int  len=0,sum=0;
    while(!v.empty())
    {
        k=*v.begin();
        vis[k]=1;
        cnt++;
        len+=dist[k].len;
        sum+=dist[k].cost;
        v.erase(k);
        for(int i=0;i<g[k].size();i++)
        {
            int to=g[k][i].to;
            if(!vis[to]&&(g[k][i].len<dist[to].len||(g[k][i].len==dist[to].len&&g[k][i].cost<dist[to].cost)))
            {
                v.erase(to);
                dist[to].len=g[k][i].len;
                dist[to].cost=g[k][i].cost;
                v.insert(to);
            }
        }
    }
    if(cnt>=n)printf("%d %d\n",len,sum);
    else printf("-1 -1\n");
}
int main()
{
    int m;
    int a,b;
    while(scanf("%d%d",&n,&m)!=INF)
    {
        for(int i=0;i<=n;i++)g[i].clear();
        for(int i=0;i<m;i++)
        {
            scanf("%d%d%d%d",&a,&b,&e.len,&e.cost);
            e.to=b;
            g[a].push_back(e);
            e.to=a;
            g[b].push_back(e);
        }
        prim(1);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值