51nod 1640 天气晴朗的魔法 prime队列+最小生成树+最大生成树+邻接表
2016-01-24 20:27
316 查看
题目:
51nod魔法学校近日开展了主题为“天气晴朗”的魔法交流活动。
N名魔法师按阵法站好,之后选取N - 1条魔法链将所有魔法师的魔力连接起来,形成一个魔法阵。
魔法链是做法成功与否的关键。每一条魔法链都有一个魔力值V,魔法最终的效果取决于阵中所有魔法链的魔力值的和。
由于逆天改命的魔法过于暴力,所以我们要求阵中的魔法链的魔力值最大值尽可能的小,与此同时,魔力值之和要尽可能的大。
现在给定魔法师人数N,魔法链数目M。求此魔法阵的最大效果。
Input
Output
Input示例
Output示例
思路:首先因为要找到生成树里面魔力值的最大值的最小值,所以可以用最小生成树跑一边,求出两个节点距离最大的点,这就是最大的了。然后用最小生成树的算法跑一边最大生成树,权值不能大于前面求出的那个值。
超时代码:
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; }
相关文章推荐
- 【NOI2001】炮兵阵地
- Android开发之按键、触摸屏和手势输入专业压力測试方法
- HTML笔记五,HTML5的多媒体支持
- [转]C# 指针之美
- python
- 计算机科学技术基础知识之标准化和知识产权基础知识
- hdu 1030 Delta-wave(数学题+找规律)
- HDOJ 5071 Chat 模拟
- lasso的今世前身
- Linux下解压缩命令
- POJ 2251 - Dungeon Master
- 计算机科学技术基础知识之多媒体知识
- 解题报告:Spell checker 模拟/string
- SQL远程过程调用失败
- 查找学生信息
- 图像判断(转)
- Multiset ------ 多重集合
- 利用face++的人脸检测实现的眼球跟随效果
- Spring学习笔记2——初识Spring MVC
- mysql图形化界面MySQL_Workbench