CodeForces

来源:互联网 发布:虚拟windows系统 编辑:程序博客网 时间:2024/05/17 03:24
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 a gold 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 ≤ 2001 ≤ 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 ≤ N1 ≤ 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 .

Examples
input
3 32 11 2 10 151 2 4 201 3 5 1
output
30


参考博客:http://blog.csdn.net/wzq_qwq/article/details/49532547

有点难度的最小生成树了,因为它有两个权值,所以我们无法找到一种最优的排序方法直接生成最小树

思路
我们想啊,我们可以枚举第一个权值gi,然后用第二个权值si做一个最小生成树,最后只要找到一个最小值就好了

所以我们可以先把gi排序(排序后枚举时下一个边集总是对上一个边集有着包含的关系),依次枚举gi的值,枚举时我们需要把si从小到大排序,然后建立最小生成树,


但是这样的话,每次都需要对si排序大大地浪费了时间,所以这个地方可以改进一下,
有这样一个规律,即每次选取成为最小生成树的边只可能是上一次最小生成树的边和这一次新加的边(或许看完代码之后再理解这句话更容易些)
因为在枚举gi时,当前的gi必定为满足最小生成树且在当前所有gi中最大的gi,所以如果这一次能够建立最小生成树,那么最小生成树中的边只可能是已经加入(即枚举过)的边

所以我们可以开一个栈记录上一次最小生成树的边,然后添加的时候只需要扫一遍这些边找到应该添加的位置即可。
复杂度O(m*n)

代码:
#include<stdio.h>#include<string.h>#include<algorithm>using namespace std;#define LL long long int#define min(a,b) (a<b?a:b)#define maxn 200+10#define maxv 50000+10const LL inf=0x3f3f3f3f3f3f3f3fll;struct edge{    int u,v,cx,cy;} e[maxv],g[maxn];int pre[maxn];int n,m,G,S;bool cmp(edge a,edge b){    if(a.cx==b.cx)        return a.cy<b.cy;    return a.cx<b.cx;}void init(){    for(int i=1; i<=n; ++i)        pre[i]=i;}int Find(int c){    if(c==pre[c])        return c;    pre[c]=Find(pre[c]);    return pre[c];}int main(){    scanf("%d%d%d%d",&n,&m,&G,&S);    for(int i=1; i<=m; ++i)        scanf("%d%d%d%d",&e[i].u,&e[i].v,&e[i].cx,&e[i].cy);    sort(e+1,e+m+1,cmp);    int top=0;    LL ans=inf;    for(int i=1; i<=m; ++i)    {        init();        g[++top]=e[i];        for(int j=top; j>=2; --j)            if(g[j].cy<g[j-1].cy)                swap(g[j],g[j-1]);        int cnt=0;        for(int j=1; j<=top; ++j)        {            int fx=Find(g[j].u),fy=Find(g[j].v);            if(fx!=fy)            {                g[++cnt]=g[j];                pre[fx]=fy;                if(cnt==n-1)                    break;            }        }        if(cnt==n-1)            ans=min(ans,(LL)e[i].cx*G+(LL)g[cnt].cy*S);        top=cnt;    }    if(ans==inf)        printf("-1\n");    else        printf("%lld\n",ans);    return 0;}

总结:
以前做的最小生成树基本上都是模板题,这一次可是学到了很多啊
1.假如有两个权值的话,可以枚举权值,寻找最优解
2.加深了对最小生成树“最小”一词的理解
3.对已经排序好的数据,仅仅是加入一个数据的话,可以通过记录上一次排序的状况,直接插入就行了
1 0