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 ...
随机推荐
- 使用 SendARP 获取 MAC 地址(使用SendARP API函数,很多相关文章)
ARP 协议地址解析协议(ARP)是通过解析网路层地址来找寻数据链路层地址的一个在网络协议包中极其重要的网络传输协议.ARP 最初在 1982 年的 RFC 826 中提出并纳入互联网标准 STD 3 ...
- 【Python练习】文件引用用户名密码登录系统
一.通过txt文件引入用户名密码 1 #coding=utf-8 from selenium import webdriver #from selenium.common.exceptions imp ...
- Prometheus+Grafana+Altermanager搭建监控系统
基本概念 Prometheus 时间序列化数据库,我的理解就是将数据打上标签,以时间维度存储.后面有机会在深入研究. Prometheus架构如下: Grafana Prometheus中存储的数据, ...
- 最新可靠好用的DNS服务器地址汇总
如果修改DNS服务器地址就可以访问google等服务,你还等什么?使用免费DNS解析服务除了去掉了运营商的各种广告,还有个最大的好处就是不会重定向或者过滤用户所访问的地址,这样就防止了很多网站被电信. ...
- Selenium Webdriver——操作隐藏的元素(四)
页面上弹出的对话框是自动化测试经常会遇到的一个问题:很多情况下对话框是一个iframe,如上一节中介绍的例子,处理起来稍微有点麻烦:但现在很多前端框架的对话框是div 形式的,这就让我们的处理变得十分 ...
- UNDFTD x Nike Air Max 97 OG Black
The UNDFTD x Nike Air Max 97 OG Black is releasing way sooner than anticipated. This collaborative r ...
- 7.10 Models -- Handling Metadata(处理元数据)
1. 随着从store中返回的records,你可能需要处理一些元数据.Metadata是伴随着特定model或者type的一种数据,而不是record. 2. 分页是使用元数据的一个常见的例子.想象 ...
- Summary: Binary Search
Iterative ways: int binarySearch (int[] a, int x) { int low = 0; int high = a.length - 1; int mid; w ...
- distinct count
实验:查询一个column的无重复记录,需要知道有多少条记录,并显示记录. 统计记录用count(*)函数,无重复记录distinct,以emp表为例. (1)先查询无重复记录 [@more@] SQ ...
- 011-/etc/resolv.conf详解