Description

题库链接

给你 \(n\) 个节点 \(m\) 条边的无向连通图。每条边有两个权值 \(c,t\) ,要你生成一棵边集为 \(\mathbb{E}\) 的生成树使得 \[\sum_{e\in \mathbb{E}}e_c \times \sum_{e\in \mathbb{E}}e_t\] 最小。

\(1\leq n\leq 200,1\leq m\leq 10000\)

Solution

令 \(x=\sum_{e\in \mathbb{E}}e_c,y=\sum_{e\in \mathbb{E}}e_t\) 。记 \(k=xy\) ,那么对于反比例函数 \(y=\frac{k}{x}\) , \(k\) 越小越贴近坐标轴。

我们将所有生成树的权值以 \((x,y)\) 的形式刻画在坐标轴上,显然满足条件的最小值一定在左下凸包上。

那么首先最极端的是单纯按 \(c\) 排序和按 \(t\) 排序得到的点 \(A,B\) 。

然后显然要找到在连线 \(AB\) 左下最远的点 \(C\) 。

由于离 \(AB\) 最远的 \(C\) 必定导致 \(S_{\Delta ABC}\) 最大。

显然就是求 \(\left(\vec{AB}\times\vec{AC}\right)_{min}\) \[\begin{aligned}\vec{AB}\times\vec{AC}&=(x_B-x_A)(y_C-y_A)-(y_B-y_A)(x_C-x_A)\\&=y_C(x_B-x_A)+x_C(y_A-y_B)+K\end{aligned}\]

其中 \(K\) 是与 \(C\) 无关的量,可以忽略。所以将所有边权改为上述式子后做一遍最小生成树就可以求出 \(C\) 了。

然后继续分治对线段 \(AC\) 和线段 \(CB\) 求解即可。递归的边界为 \(\vec{AB}\times\vec{AC}\geq 0\) 。

Code

//It is made by Awson on 2018.3.7
#include <bits/stdc++.h>
#define LL long long
#define dob complex<double>
#define Abs(a) ((a) < 0 ? (-(a)) : (a))
#define Max(a, b) ((a) > (b) ? (a) : (b))
#define Min(a, b) ((a) < (b) ? (a) : (b))
#define Swap(a, b) ((a) ^= (b), (b) ^= (a), (a) ^= (b))
#define writeln(x) (write(x), putchar('\n'))
#define lowbit(x) ((x)&(-(x)))
using namespace std;
const int N = 200, M = 10000;
void read(int &x) {
char ch; bool flag = 0;
for (ch = getchar(); !isdigit(ch) && ((flag |= (ch == '-')) || 1); ch = getchar());
for (x = 0; isdigit(ch); x = (x<<1)+(x<<3)+ch-48, ch = getchar());
x *= 1-2*flag;
}
void print(int x) {if (x > 9) print(x/10); putchar(x%10+48); }
void write(int x) {if (x < 0) putchar('-'); print(Abs(x)); } int n, m, fa[N+5];
struct tt {
int u, v, w, c, t;
bool operator < (const tt &b) const {return w < b.w; }
}edge[M+5];
struct node {
int x, y;
node(int _x = 0, int _y = 0) {x = _x, y = _y; }
int operator * (const node &b) const {return x*b.y-y*b.x; }
node operator + (const node &b) {node t; t.x = x+b.x, t.y = y+b.y; return t; }
node operator - (const node &b) {node t; t.x = x-b.x, t.y = y-b.y; return t; }
void print() {write(x), putchar(' '), writeln(y); }
}ans, A, B;
int find(int x) {return fa[x] ? fa[x] = find(fa[x]) : x; } void update(node &ans, node x) {if (1ll*ans.x*ans.y > 1ll*x.x*x.y || (1ll*ans.x*ans.y == 1ll*x.x*x.y && ans.x > x.x)) ans = x; }
bool judge(node A, node B, node C) {return (B-A)*(C-A) >= 0; }
node kruskal() {
memset(fa, 0, sizeof(fa)); int cnt = 0; node tmp;
sort(edge+1, edge+1+m);
for (int i = 1; i <= m; i++) {
if (find(edge[i].u)^find(edge[i].v)) {
++cnt; fa[find(edge[i].u)] = find(edge[i].v);
tmp = tmp+node(edge[i].c, edge[i].t);
if (cnt == n-1) break;
}
}
return tmp;
}
void doit(node A, node B) {
int x = B.x-A.x, y = A.y-B.y; node C;
for (int i = 1; i <= m; i++) edge[i].w = x*edge[i].t+y*edge[i].c;
update(ans, C = kruskal());
if (judge(A, B, C)) return;
doit(A, C), doit(C, B);
}
void work() {
read(n), read(m);
for (int i = 1; i <= m; i++) read(edge[i].u), read(edge[i].v), read(edge[i].c), read(edge[i].t), ++edge[i].u, ++edge[i].v;
for (int i = 1; i <= m; i++) edge[i].w = edge[i].c;
A = ans = kruskal();
for (int i = 1; i <= m; i++) edge[i].w = edge[i].t;
update(ans, B = kruskal());
doit(A, B);
ans.print();
}
int main() {
work(); return 0;
}

[COGS 2401]Time is Money的更多相关文章

  1. [HNOI 2014]画框

    Description 题库链接 \(T\) 组询问,每组询问给你个 \(2\times N\) 的带权二分图,两个权值 \(a,b\) ,让你做匹配使得 \[\sum a\times \sum b\ ...

  2. 【COGS 254】【POI 2001】交通网络图

    http://www.cogs.top/cogs/problem/problem.php?pid=254 dist[i]表示能最早到达i点的时间.这样就可以用最短路模型来转移了. #include&l ...

  3. 【COGS】894. 追查坏牛奶

    http://cojs.tk/cogs/problem/problem.php?pid=894 题意:n个点m条边的加权网络,求最少边数的按编号字典序最小的最小割.(n<=32, m<=1 ...

  4. 【COGS】147. [USACO Jan08] 架设电话线(二分+spfa)

    http://cojs.tk/cogs/problem/problem.php?pid=147 学到新姿势了orz 这题求的是一条1-n的路径的最大路径最小. 当然是在k以外的. 我们可以转换一下. ...

  5. 【COGS & USACO Training】710. 命名那个数字(hash+水题+dfs)

    http://cojs.tk/cogs/problem/problem.php?pid=710 近日开始刷水... 此题我为了练一下hash...但是hash跑得比暴力还慢.. 不言而喻... #in ...

  6. 【COGS & USACO】896. 圈奶牛(凸包)

    http://cojs.tk/cogs/problem/problem.php?pid=896 我的计算几何入门题... 看了看白书的计算几何部分,,恩好嘛.. 乃们都用向量!!!! 干嘛非要将2个点 ...

  7. 【COGS】714. USACO 1.3.2混合牛奶(贪心+水题)

    http://cojs.tk/cogs/problem/problem.php?pid=714 在hzwer的刷题记录上,默默地先跳过2题T_T...求凸包和期望的..T_T那是个啥..得好好学习 看 ...

  8. Cogs 97. [NOIP2007] 树网的核 Floyd

    题目: http://cojs.tk/cogs/problem/problem.php?pid=97 97. [NOIP2007] 树网的核 ★☆   输入文件:core.in   输出文件:core ...

  9. bzoj 2401: 陶陶的难题I 数论

    2401: 陶陶的难题I Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 89  Solved: 24[Submit][Status] Descript ...

随机推荐

  1. git基本用法

    基本用法(下)           一.实验说明 本节实验为 Git 入门第二个实验,继续练习最常用的git命令. 1.1 实验准备 在进行该实验之前,可以先clone一个练习项目gitproject ...

  2. DML数据操作语言之复杂查询

    1.视图(View) 我们知道,在关系型数据库中,用来保存实际数据记录的是数据表.和表同等概念也是用来保存东西是:视图. 但是数据表是用来保存实际数据记录的,而视图是用来保存常用select语句的. ...

  3. bzoj千题计划274:bzoj3779: 重组病毒

    http://www.lydsy.com/JudgeOnline/problem.php?id=3779 有一棵树,初始每个节点有不同的颜色 操作1:根节点到x的路径上的点 染上一种没有出现过的颜色 ...

  4. requestAnimationFrame Web中写动画的另一种选择

    HTML5和CSS3盛行的今天  动画变得很简单实现 我们可以用transition . animation + keyframe .也可以用canvas等 我在上一篇 点击回到顶部的文章中发现的这个 ...

  5. django models的点查询/跨表查询/双下划线查询

    django models 在日常的编程中,我们需要建立数据库模型 而往往会用到表与表之间的关系,这就比单表取数据要复杂一些 在多表之间发生关系的情形下,我们如何利用models提供的API的特性获得 ...

  6. php的格式化数字函数

    php格式化数字:位数不足前面加0补足 php格式化数字:位数不足前面加0补足 感谢:http://www.cnblogs.com/xiaochaohuashengmi/archive/2011/12 ...

  7. Struts2 配置文件小结

    每次写的博文都被管理员都被移出首页,好气!还希望有哪位大神可以指点迷津-- struts2 配置文件的 result 节点 result 节点是 action 节点的子节点,他代表着 action 方 ...

  8. 链家2018春招Java工程师编程题题解

    Light 题目描述 在小红家里面,有n组开关,触摸每个开关,可以使得一组灯泡点亮.现在问你,使用这n组开关,最多能够使得多少个灯泡点亮呢? 输入 第一行一个n,表示有n组开关.接下来n行,每行第一个 ...

  9. python 字符串的方法

    capitalize() 把字符串的第一个字符改为大写 casefold() 把整个字符串的所有字符改为小写 center(width) 将字符串居中,并使用空格填充至长度 width 的新字符串 c ...

  10. Docker学习笔记 - 在运行中的容器内启动新进程

    docker psdoker top dc1 # 容器情况# 在运行中的容器内启动新进程docker exec [-d] [-i] [-t] 容器名 [command] [args]docker ex ...