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 gisi 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

Input
3 3
2 1
1 2 10 15
1 2 4 20
1 3 5 1
Output
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)的时间内处理完。

  1. 在一棵树上添加一条边,会形成一个环,找到这个环,删去其中s值最大的一条边(由于插入的边不能被删去,这个的过程就是树上两点间的简单路径找s值最大的一条边,这个过程可以用LCT做到单次操作$O\left(\log n\right)$)。因为上一个生成树最有n个点,n - 1条边,所以时间复杂度为O(n)
  2. 用一个数组维护,然后插入排序,接着做一次最小生成树。时间复杂度仍然是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 - 最小生成树的更多相关文章

  1. CodeForces - 76A:Gift (最小生成树 解决单调性问题是思想)

    题意:给定N点M边的无向连通图,每条边有两个权值(g,s). 给定G,S. 让你给出一组(g0,s0)使得图中仅留下g<=g0, s<=s0的边之后,依然连通,并求Gg0+Ss0的最小值. ...

  2. CF76A.Gift [最小生成树]

    CF76A.Gift 题意:noi2014魔法森林弱化版QwQ,最小化\(max(g_i)*G + max(s_i)*S\)的最小生成树 考虑按g升序加边,用已在生成树中的边和新加入的边求当前最小生成 ...

  3. codeforces 1245D(最小生成树)

    题面链接:https://codeforces.com/problemset/problem/1245/D 题意大概是给你一些城市的坐标,可以在城市中建立发电站,也可以让某个城市和已经建好发电站的城市 ...

  4. CodeForces 141E: ...(最小生成树)

    [条件转换] 两两之间有且只有一条简单路径<==>树 题意:一个图中有两种边,求一棵生成树,使得这棵树中的两种边数量相等. 思路: 可以证明,当边的权是0或1时,可以生成最小生成树到最大生 ...

  5. 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 ...

  6. Educational Codeforces Round 3 E. Minimum spanning tree for each edge (最小生成树+树链剖分)

    题目链接:http://codeforces.com/contest/609/problem/E 给你n个点,m条边. 问枚举每条边,问你加这条边的前提下组成生成树的权值最小的树的权值和是多少. 先求 ...

  7. 【最小生成树】Codeforces 707B Bakery

    题目链接: http://codeforces.com/problemset/problem/707/B 题目大意: 给你N个点M条无向边,其中有K个面粉站,现在一个人要在不是面粉站的点上开店,问到面 ...

  8. CF Educational Codeforces Round 3 E. Minimum spanning tree for each edge 最小生成树变种

    题目链接:http://codeforces.com/problemset/problem/609/E 大致就是有一棵树,对于每一条边,询问包含这条边,最小的一个生成树的权值. 做法就是先求一次最小生 ...

  9. Codeforces 1120D Power Tree [最小生成树]

    洛谷 Codeforces 这题怎么一个中文题解都没有,是不是你们都认为太水了-- 思路 显然可以用dfs序把每个节点变成给一个区间的叶子节点加上某个数. 显然把叶子序列差分一下变为\(a_1,a_2 ...

随机推荐

  1. PDB、PD、PMP、RTB哪个更好?为品牌主解锁程序化购买的选择技巧

    PDB.PD.PMP.RTB哪个更好?为品牌主解锁程序化购买的选择技巧 https://baijiahao.baidu.com/s?id=1620277114893208111&wfr=spi ...

  2. YYLabel计算富文本高度-膜拜大神

    http://www.jianshu.com/p/07cd655fee7e YYTextLayout *layout = [YYTextLayout layoutWithContainerSize:C ...

  3. centos7设置iptables

    https://www.linuxidc.com/Linux/2017-10/147238.htm

  4. count(*) count(1) count(column)区别

    count(*) 和count(1)的效果是一样的.在某些情况下效率不一样.也会统计包含null的记录. count(column)会返回当前字段不为null的记录数.

  5. Python命令行解析库argparse(转)

    原文:http://www.cnblogs.com/linxiyue/p/3908623.html 2.7之后python不再对optparse模块进行扩展,python标准库推荐使用argparse ...

  6. mysql python pymysql模块 增删改查 查询 字典游标显示

    我们看到取得结果是一个元祖,但是不知道是哪个字段的,如果字段多的时候,就比较麻烦 ''' (1, 'mike', '123') (2, 'jack', '456') ''' 用字典显示查询的结果,也可 ...

  7. mysql 数据操作 多表查询 多表连接查询 外链接之左连接 右连接

    1.外链接之左连接:优先显示左表全部记录   left join 在内连接的基础上保留左表的记录 即便左表有一条记录和右表没有关系,也把他留下 mysql> select * from empl ...

  8. Y2K Accounting Bug(poj2586)

    题意: 有一个公司由于某个病毒使公司赢亏数据丢失,但该公司每月的 赢亏是一个定数,要么一个月赢利s,要么一月亏d.现在ACM只知道该公司每五个月有一个赢亏报表,而且每次报表赢利情况都为亏.在一年中这样 ...

  9. CentOS7更改Docker默认镜像和容器存储位置

    图片出处:https://bobcares.com/wp-content/uploads/docker-change-directory.jpg 一.Why? 通常,当你开始使用docker时,我们并 ...

  10. python 一个.py文件如何调用另一个.py文件中的类和函数

    原文地址https://blog.csdn.net/winycg/article/details/78512300 在同一个文件夹下 调用函数: