CodeForces 76A Gift - 最小生成树
The kingdom of Olympia consists of N cities and M bidirectional roads. Each road connects exactly two cities and two cities can be connected with more than one road. Also it possible that some roads connect city with itself making a loop.
All roads are constantly plundered with bandits. After a while bandits became bored of wasting time in road robberies, so they suggested the king of Olympia to pay off. According to the offer, bandits want to get a gift consisted of gold and silver coins. Offer also contains a list of restrictions: for each road it is known gi — the smallest amount of gold and si — the smallest amount of silver coins that should be in the gift to stop robberies on the road. That is, if the gift contains agold and b silver coins, then bandits will stop robberies on all the roads that gi ≤ a and si ≤ b.
Unfortunately kingdom treasury doesn't contain neither gold nor silver coins, but there are Olympian tugriks in it. The cost of one gold coin in tugriks is G, and the cost of one silver coin in tugriks is S. King really wants to send bandits such gift that for any two cities there will exist a safe path between them. Your task is to find the minimal cost in Olympian tugriks of the required gift.
Input
The first line of the input contains two integers N and M (2 ≤ N ≤ 200, 1 ≤ M ≤ 50 000) — the number of cities and the number of roads, respectively. The second line contains two integers G and S (1 ≤ G, S ≤ 109) — the prices of gold and silver coins in tugriks. The following M lines contain information about the offer. Each of the records in list is given as four integers xi, yi, gi, si, where xi and yi are the numbers of cities that the road connects and gi, si are minimal gold and silver coins requirements for the i-th road (1 ≤ xi, yi ≤ N, 1 ≤ gi, si ≤ 109). Cities are numbered from 1 to N. It is possible that there are more than one road between a pair of cities. It is possible that a road connects the city with itself.
Output
The output should contain the minimal cost of the gift in Olympian tugriks. If there is no gift that satisfies the given requirements output .
Example
3 3
2 1
1 2 10 15
1 2 4 20
1 3 5 1
30
题目大意是说每条边,带两条权值g,s,给定G和S,设a为所有使用的边中g的最大值,b为所有使用的边中s的最大值,求连通n个城市的最小的(a * G + b * S)
首先思考暴力吧,按照第一种权值给边排序,然后Kruskal乱搞,总时间复杂度$O\left(m^{2}\log m\right)$,高兴地发现这么会严重TLE。
继续思考,二分第一种权值,然后Kruskal顶上,总时间复杂度$O\left(m\cdot \log^{2}m\right)$,看起来可以过,然而我可以举出不满足二分条件的反例。假如G值特别小,S值特别大,边数远远大于点数,一条边g值比较大,但是s值非常的小,二分的话很可能会忽略这一条边,导致答案是错的。
继续思考人生。继续第一种思路,先按照第一种权值进行排序,考虑上一次的最小生成树,每次只会添加一条边,因此有两种方法可以在O(n)的时间内处理完。
- 在一棵树上添加一条边,会形成一个环,找到这个环,删去其中s值最大的一条边(由于插入的边不能被删去,这个的过程就是树上两点间的简单路径找s值最大的一条边,这个过程可以用LCT做到单次操作$O\left(\log n\right)$)。因为上一个生成树最有n个点,n - 1条边,所以时间复杂度为O(n)
- 用一个数组维护,然后插入排序,接着做一次最小生成树。时间复杂度仍然是O(n)
每次生成完一棵树就更新答案就行了。
贡献一堆WA,ans的初值不能设小了,至少(1 << 61)吧!
Code
/**
* CodeForces
* Problem#76A
* Accepted
* Time:248ms
* Memory:2820k
*/
#include<iostream>
#include<fstream>
#include<sstream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cctype>
#include<cmath>
#include<ctime>
#include<map>
#include<stack>
#include<set>
#include<queue>
#include<vector>
#ifndef WIN32
#define AUTO "%lld"
#else
#define AUTO "%I64d"
#endif
using namespace std;
typedef bool boolean;
#define inf 0xfffffff
#define smin(a, b) (a) = min((a), (b))
#define smax(a, b) (a) = max((a), (b))
template<typename T>
inline boolean readInteger(T& u) {
char x;
int aFlag = ;
while(!isdigit((x = getchar())) && x != '-' && x != -);
if(x == -) {
ungetc(x, stdin);
return false;
}
if(x == '-') {
aFlag = -;
x = getchar();
}
for(u = x - ''; isdigit((x = getchar())); u = u * + x - '');
u *= aFlag;
ungetc(x, stdin);
return true;
} typedef class union_found{
public:
int *f;
int points;
union_found():f(NULL), points() {}
union_found(int points):points(points) {
f = new int[(const int)(points + )];
}
int find(int x) {
if(f[x] != x) return f[x] = find(f[x]);
return f[x];
}
void unit(int fa, int so) {
int ffa = find(fa);
int fso = find(so);
f[fso] = ffa;
}
boolean connected(int a, int b) {
return find(a) == find(b);
}
void clear() {
for(int i = ; i <= points; i++)
f[i] = i;
}
}union_found; typedef class Edge {
public:
int from;
int end;
int g;
int s;
Edge(int from = , int end = , int g = , int s = ):from(from), end(end), g(g), s(s) { }
}Edge; int n, m;
long long G, S;
Edge* edges; inline void init() {
readInteger(n);
readInteger(m);
readInteger(G);
readInteger(S);
edges = new Edge[(const int)(m + )];
for(int i = ; i <= m; i++) {
readInteger(edges[i].from);
readInteger(edges[i].end);
readInteger(edges[i].g);
readInteger(edges[i].s);
}
} boolean cmp(const Edge& a, const Edge& b) {
if(a.g != b.g) return a.g < b.g;
return a.s < b.s;
} int top = ;
Edge *x;
union_found uf;
long long g0 = , s0 = ;
long long res = (1LL << );
inline void solve() {
x = new Edge[(const int)(n + )];
sort(edges + , edges + m + , cmp);
uf = union_found(n);
for(int i = ; i <= m; i++) {
uf.clear();
x[++top] = edges[i];
for(int j = top; j > ; j--)
if(x[j].s < x[j - ].s)
swap(x[j], x[j - ]);
g0 = , s0 = ;
int fin = ;
for(int j = ; j <= top; j++) {
if(!uf.connected(x[j].from, x[j].end)) {
x[++fin] = x[j];
smax(g0, (long long)x[j].g);
smax(s0, (long long)x[j].s);
uf.unit(x[j].from, x[j].end);
if(fin == n - ) break;
}
}
if(fin == n - )
smin(res, g0 * G + s0 * S);
top = fin;
}
if(res == (1LL << ))
printf("-1\n");
else printf(AUTO"\n", res);
} int main() {
init();
solve();
return ;
}
CodeForces 76A Gift - 最小生成树的更多相关文章
- CodeForces - 76A:Gift (最小生成树 解决单调性问题是思想)
题意:给定N点M边的无向连通图,每条边有两个权值(g,s). 给定G,S. 让你给出一组(g0,s0)使得图中仅留下g<=g0, s<=s0的边之后,依然连通,并求Gg0+Ss0的最小值. ...
- CF76A.Gift [最小生成树]
CF76A.Gift 题意:noi2014魔法森林弱化版QwQ,最小化\(max(g_i)*G + max(s_i)*S\)的最小生成树 考虑按g升序加边,用已在生成树中的边和新加入的边求当前最小生成 ...
- codeforces 1245D(最小生成树)
题面链接:https://codeforces.com/problemset/problem/1245/D 题意大概是给你一些城市的坐标,可以在城市中建立发电站,也可以让某个城市和已经建好发电站的城市 ...
- CodeForces 141E: ...(最小生成树)
[条件转换] 两两之间有且只有一条简单路径<==>树 题意:一个图中有两种边,求一棵生成树,使得这棵树中的两种边数量相等. 思路: 可以证明,当边的权是0或1时,可以生成最小生成树到最大生 ...
- Codeforces Educational Codeforces Round 3 B. The Best Gift 水题
B. The Best Gift 题目连接: http://www.codeforces.com/contest/609/problem/B Description Emily's birthday ...
- Educational Codeforces Round 3 E. Minimum spanning tree for each edge (最小生成树+树链剖分)
题目链接:http://codeforces.com/contest/609/problem/E 给你n个点,m条边. 问枚举每条边,问你加这条边的前提下组成生成树的权值最小的树的权值和是多少. 先求 ...
- 【最小生成树】Codeforces 707B Bakery
题目链接: http://codeforces.com/problemset/problem/707/B 题目大意: 给你N个点M条无向边,其中有K个面粉站,现在一个人要在不是面粉站的点上开店,问到面 ...
- CF Educational Codeforces Round 3 E. Minimum spanning tree for each edge 最小生成树变种
题目链接:http://codeforces.com/problemset/problem/609/E 大致就是有一棵树,对于每一条边,询问包含这条边,最小的一个生成树的权值. 做法就是先求一次最小生 ...
- Codeforces 1120D Power Tree [最小生成树]
洛谷 Codeforces 这题怎么一个中文题解都没有,是不是你们都认为太水了-- 思路 显然可以用dfs序把每个节点变成给一个区间的叶子节点加上某个数. 显然把叶子序列差分一下变为\(a_1,a_2 ...
随机推荐
- python数据结构之树(二分查找树)
本篇学习笔记记录二叉查找树的定义以及用python实现数据结构增.删.查的操作. 二叉查找树(Binary Search Tree) 简称BST,又叫二叉排序树(Binary Sort Tree),是 ...
- Linux目录【持续更新中】
故障排除 服务器为什么这么慢?耗尽了CPU.RAM和磁盘I/O资源 服务 ELK服务基础 基础 常用命令 curl命令 Nginx服务基础 Nginx正向代理配置 Nginx文件下载服务器 Nginx ...
- 2015 湘潭大学程序设计比赛(Internet)--G题-人生成就
人生成就 Accepted : 54 Submit : 104 Time Limit : 10000 MS Memory Limit : 65536 KB 题目描述 人生就像一个n*n的矩阵, ...
- chown 命令
root@localhost ~]# .txt # 同时修改文件属主和属组 !chown 执行上一个chown命令
- 便于理解mysql内幕的各种逻辑图组
便于理解mysql内幕的各种逻辑图组 http://blog.sina.com.cn/s/blog_445e807b0101ggtl.html 以下是个人一直以来从网络等各种途径收集到的一些对理解my ...
- Vue 命令
vue是数据渲染使用:axios,官网:https://www.kancloud.cn/yunye/axios/234845 || https://www.npmjs.com/search? ...
- GNS3的使用2
IDE值没算好,巨卡.重新安装,重新算值.速度快了不少 IDE值:选出现次数多,并且数字大的 2960的选256M 另外加了2个模拟器:ASA防火墙.juniper路由器
- 机器学习理论基础学习16---高斯网络(GN)
一.高斯网络(高斯图模型)总体介绍 概率图模型分为三种:贝叶斯网络,马尔科夫随机场以及高斯网络:而高斯网络又可以根据有向无向细分为高斯贝叶斯网络和高斯马尔科夫随机场 二.高斯贝叶斯网络 1.高斯贝叶斯 ...
- 用python参加Kaggle的些许经验总结(收藏)
Step1: Exploratory Data Analysis EDA,也就是对数据进行探索性的分析,一般就用到pandas和matplotlib就够了.EDA一般包括: 每个feature的意义, ...
- [lr] 常用快捷键
界面基本操作 F5 : 隐藏/显示上部面板 F6 : 隐藏/显示下部面板 F7 : 隐藏/显示左部面板 F8 ...