【BZOJ】2395: [Balkan 2011]Timeismoney
生活随笔
收集整理的這篇文章主要介紹了
【BZOJ】2395: [Balkan 2011]Timeismoney
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
題解
最小乘積生成樹!
我們把,x的總和和y的總和作為x坐標(biāo)和y左邊,畫在坐標(biāo)系上
我們選擇兩個(gè)初始點(diǎn),一個(gè)是最靠近y軸的A,也就是x總和最小,一個(gè)是最靠近x軸的B,也就是y總和最小
連接兩條直線,在這條直線上面的點(diǎn)都不用考慮了
我們選一個(gè)離直線最遠(yuǎn)的點(diǎn)C,且在直線下方,我們用叉積考慮這個(gè)東西,也就是……面積最大!我們?nèi)绻米钚∩蓸涞脑?#xff0c;只要讓面積是負(fù)的就好了
推一下式子,發(fā)現(xiàn)是\((A.y - B.y) * C.x + (B.x - A.x) * C.y\)我們發(fā)現(xiàn)就是把邊設(shè)置成
\((A.y - B.y) * E[i].c + (B.x - A.x) * E[i].t\)做一遍最小生成樹
找到C點(diǎn)后遞歸處理A,C和C,B即可
邊界是兩點(diǎn)連線下方?jīng)]有點(diǎn)也就是叉積大于等于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('\n') 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\n",ans.x,ans.y); } int main() { #ifdef ivorysifreopen("f1.in","r",stdin); #endifSolve();return 0; }轉(zhuǎn)載于:https://www.cnblogs.com/ivorysi/p/9071158.html
總結(jié)
以上是生活随笔為你收集整理的【BZOJ】2395: [Balkan 2011]Timeismoney的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: delphi 中几种多线程操作方式
- 下一篇: 免费接口(http://www.bejs