1. 程式人生 > >一道圖論好題

一道圖論好題

can 解釋 limit smart 之間 存在 cstring pac 題目

一道圖論好題

Time Limit:1000ms Memory Limit:128MB

題目描述

LYK有一張無向圖G={V,E},這張無向圖有n個點m條邊組成。並且這是一張帶權圖,不僅有邊權還有點權。

LYK給出了一個子圖的定義,一張圖G’={V’,E’}被稱作G的子圖,當且僅當

·G’的點集V’包含於G的點集V。

·對於E中的任意兩個點a,b∈V’,當(a,b)∈E時,(a,b)一定也屬於E’,並且連接這兩個點的邊的邊權是一樣的。

LYK給一個子圖定義了它的價值,它的價值為:點權之和與邊權之和的比。

LYK想找到一個價值最大的非空子圖,所以它來找你幫忙啦。

輸入格式

第一行兩個數n,m表示一張n個點m條邊的圖。

第二行n個數ai表示點權。

接下來m行每行三個數u,v,z,表示有一條連接u,v的邊權為z的無向邊。數據保證任意兩個點之間最多一條邊相連,並且不存在自環。

輸出格式

你需要輸出這個價值最大的非空子圖的價值,由於它是一個浮點數,你只需要保留小數點後兩位有效數字。

輸入樣例

3 3

2 3 4

1 2 3

1 3 4

2 3 5

輸出樣例

1.67

樣例解釋

選擇1,2兩個點,則價值為5/3=1.67。

對於20%的數據n=2

對於50%的數據n<=5

對於100%的數據1<=n,m<=100000,1<=ai,z<=1000。

題解

選擇連邊,價值為(a+c)/(b+d+e)。

不選,價值為max(a/b,c/d)。

易證max(a/b,c/d)>(a+c)/(b+d+e)。

證明過程:

假設a/b>=c/d,那麽a/b-c/d=(ad-bc)/bd>=0,所以ad-bc>=0。

所以a/b-(a+c)/(b+d)=(a(b+d)-b(a+c))/b(b+d)=(ad-bc)/b(b+d)>=0,所以a/b>=(a+c)/(b+d),所以a/b>(a+c)/(b+d+e)。

因為子圖非空,所以只選一條邊上的兩點一定最優。

技術分享

代碼

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
using namespace std;
const int N=100005;
int n,m;
int a[N];
double ans;
int main(){
    scanf("%d%d",&n,&m);
    for(i=1;i<=n;i++)scanf("%d",&a[i]);
    int u,v,w;
    for(i=1;i<=m;i++){
        scanf("%d%d%d",&u,&v,&w);
        ans=max(ans,(double)(a[u]+a[v])/(double)w);
    }
    printf("%.2f\n",ans);
    return 0;
}

一道圖論好題