zoukankan      html  css  js  c++  java
  • 【BZOJ】2395: [Balkan 2011]Timeismoney

    题解

    最小乘积生成树!

    我们把,x的总和和y的总和作为x坐标和y左边,画在坐标系上

    我们选择两个初始点,一个是最靠近y轴的A,也就是x总和最小,一个是最靠近x轴的B,也就是y总和最小
    连接两条直线,在这条直线上面的点都不用考虑了

    我们选一个离直线最远的点C,且在直线下方,我们用叉积考虑这个东西,也就是……面积最大!我们如果用最小生成树的话,只要让面积是负的就好了
    推一下式子,发现是((A.y - B.y) * C.x + (B.x - A.x) * C.y)我们发现就是把边设置成
    ((A.y - B.y) * E[i].c + (B.x - A.x) * E[i].t)做一遍最小生成树

    找到C点后递归处理A,C和C,B即可

    边界是两点连线下方没有点也就是叉积大于等于0

    代码

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #include <ctime>
    #include <vector>
    #include <set>
    //#define ivorysi
    #define eps 1e-8
    #define mo 974711
    #define pb push_back
    #define mp make_pair
    #define pii pair<int,int>
    #define fi first
    #define se second
    #define MAXN 10005
    #define space putchar(' ')
    #define enter putchar('
    ')
    using namespace std;
    typedef long long int64;
    typedef unsigned int u32;
    typedef unsigned long long u64;
    typedef double db;
    const int64 MOD = 1000000007;
    template<class T>
    void read(T &res) {
        res = 0;char c = getchar();T f = 1;
        while(c < '0' || c > '9') {
    	if(c == '-') f = -1;
    	c = getchar();
        }
        while(c >= '0' && c <= '9') {
    	res = res * 10 + c - '0';
    	c = getchar();
        }
        res *= f;
    }
    template<class T>
    void out(T x) {
        if(x < 0) putchar('-');
        if(x >= 10) {
    	out(x / 10);
        }
        putchar('0' + x % 10);
    }
    int N,M;
    struct Point {
        int64 x,y;
        int64 v;
        Point(){};
        Point(int64 _x,int64 _y) {
    	x = _x;y = _y;v = x * y;
        }
        friend bool operator < (const Point &a,const Point &b) {
    	return a.v < b.v || (a.v == b.v && a.x < b.x);
        }
    }ans;
    struct Edge {
        int u,v;
        int64 c,t,w;
        Edge(){}
        Edge(int _u,int _v,int64 _c,int64 _t) {
    	u = _u;v = _v;c = _c;t = _t;
        }
        friend bool operator < (const Edge &a,const Edge &b) {
    	return a.w < b.w || (a.w == b.w && a.c < b.c);
        }
    }E[MAXN];
    int fa[205];
    int getfa(int u) {
        return fa[u] == u ? u : fa[u] = getfa(fa[u]);
    }
    Point kruskal() {
        sort(E + 1,E + M + 1);
        Point res = Point(0,0);
        for(int i = 1 ; i <= N ; ++i) fa[i] = i;
        for(int i = 1 ; i <= M ; ++i) {
    	if(getfa(E[i].u) != getfa(E[i].v)) {
    	    fa[getfa(E[i].u)] = getfa(E[i].v);
    	    res.x += E[i].c;res.y += E[i].t;
    	}
        }
        res.v = res.x * res.y;
        if(res < ans) ans = res;
        return res;
    }
    void Work(Point A,Point B) {
        for(int i = 1 ; i <= M ; ++i) {
    	E[i].w = (A.y - B.y) * E[i].c + (B.x - A.x) * E[i].t;
        }
        Point r = kruskal();
        if((A.x - r.x) * (B.y - r.y) - (A.y - r.y) * (B.x - r.x) >= 0) return;
        Work(A,r);
        Work(r,B);
    }
    void Solve() {
        read(N);read(M);
        int u,v;
        int64 c,t;
        for(int i = 1 ; i <= M ; ++i) {
    	read(u);read(v);read(c);read(t);
    	++u;++v;
    	E[i] = Edge(u,v,c,t);
        }
        ans.v = 1e18;
        for(int i = 1 ; i <= M ; ++i) {
    	E[i].w = E[i].c;
        }
        Point A = kruskal();
        for(int i = 1 ; i <= M ; ++i) {
    	E[i].w = E[i].t;
        }
        Point B = kruskal();
        Work(A,B);
        printf("%lld %lld
    ",ans.x,ans.y);
    }
    int main() {
    #ifdef ivorysi
        freopen("f1.in","r",stdin);
    #endif
        Solve();
        return 0;
    }
    
  • 相关阅读:
    Eclipse安装Hadoop插件
    (转)Ubuntu14.0.4中hadoop2.4.0伪分布模式配置
    Hadoop--DataNode无法启动
    启动与关闭hadoop
    hadoop中执行命令时发生错误
    strings命令
    Deriving data from ElasticSearch Engine
    elasticsearch data importing
    reading words in your computer and changing to female voice, linux festival text2wave saving wav files
    DDNS client on a Linux machine
  • 原文地址:https://www.cnblogs.com/ivorysi/p/9071158.html
Copyright © 2011-2022 走看看