CodeForces 444A DZY Loves Physics
题目大意
给定一张无向图,其中每个点有一个权值AuA_uAu?,每条边有一个权值Bu,vB_{u,v}Bu,v?,要求找出一个子图,使得子图连通且任意两点间存在边则一定要被选中。
求出选出的子图中点权之和除以边权之和的最大值。
分析
结论: 这个子图中仅包含一条边和它的两个端点。
然后就枚举一条边,计算它的答案。然后就完了。。。
证明: 我们只需要证明对于三个连成一条链的点u,v,wu,v,wu,v,w(u,wu,wu,w是端点),选择u,v,wu,v,wu,v,w取不到最大值即可。
采用反证法:假设选择了u,v,wu,v,wu,v,w取得了最大值,那么我们可以得到如下不等式:
{Au+Av+AwBu,v+Bv,w≥Au+AvBu,vAu+Av+AwBu,v+Bv,w≥Aw+AvBv,w\begin{cases}\frac{A_u+A_v+A_w}{B_{u,v}+B_{v,w}}\ge \frac{A_u+A_v}{B_{u,v}}\\\frac{A_u+A_v+A_w}{B_{u,v}+B_{v,w}}\ge \frac{A_w+A_v}{B_{v,w}}\end{cases} { Bu,v?+Bv,w?Au?+Av?+Aw??≥Bu,v?Au?+Av??Bu,v?+Bv,w?Au?+Av?+Aw??≥Bv,w?Aw?+Av???
简单整理一下得到:
{Aw≥AvBu,v+AuBv,wBu,vAu≥AwBu,v+AvBu,vBv,w\begin{cases}A_w\ge \frac{A_vB_{u,v}+A_uB_{v,w}}{B_{u,v}}\\A_u\ge\frac{A_wB_{u,v}+A_vB_{u,v}}{B_{v,w}}\end{cases} { Aw?≥Bu,v?Av?Bu,v?+Au?Bv,w??Au?≥Bv,w?Aw?Bu,v?+Av?Bu,v???
我们把上面的那个不等式代入下面去得到:
Au≥AvBu,v+AuBv,wBu,v×Bu,v+AvBu,vBv,w=AvBu,v+AuBv,w+AvBu,vBv,w=Au+2AvBu,vBv,w\begin{aligned}A_u &\ge \frac{\frac{A_vB_{u,v}+A_uB_{v,w}}{B_{u,v}}\times B_{u,v}+A_vB_{u,v}}{B_{v,w}}\\ &=\frac{A_vB_{u,v}+A_uB_{v,w}+A_vB_{u,v}}{B_{v,w}}\\ &=A_u+\frac{2A_vB_{u,v}}{B_{v,w}}\end{aligned} Au??≥Bv,w?Bu,v?Av?Bu,v?+Au?Bv,w??×Bu,v?+Av?Bu,v??=Bv,w?Av?Bu,v?+Au?Bv,w?+Av?Bu,v??=Au?+Bv,w?2Av?Bu,v???
移项得到:
2AvBu,vBv,w≤0\frac{2A_vB_{u,v}}{B_{v,w}}\le 0 Bv,w?2Av?Bu,v??≤0
由于题目中给定的点权和边权都是正数,所以这个不等式不成立,所以选择一条链不能得到最大值。
故当点权和除以边权和最大时,子图中只有一条边和它的两个端点
参考代码
#include <cstdio>
#include <algorithm>
using namespace std;const int Maxn = 500;int N, M;
int A[Maxn + 5];int main() {
#ifdef LOACLfreopen("in.txt", "r", stdin);freopen("out.txt", "w", stdout);
#endifdouble ans = 0;scanf("%d %d", &N, &M);for(int i = 1; i <= N; i++)scanf("%d", &A[i]);for(int i = 1; i <= M; i++) {
int u, v, w;scanf("%d %d %d", &u, &v, &w);ans = max(ans, 1.0 * (A[u] + A[v]) / w);}printf("%.9f\n", ans);return 0;
}