您的位置:首页 > 其它

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

2016-01-24 20:27 316 查看
题目:

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: