日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

[HNOI2009]最小圈 (二分答案+负环)

發布時間:2025/4/16 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [HNOI2009]最小圈 (二分答案+负环) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題面:[HNOI2009]最小圈

題目描述:

考慮帶權的有向圖\(G=(V,E)\)以及\(w:E\rightarrow R\),每條邊\(e=(i,j)(i\neq j,i\in V,j\in V)\)的權值定義為\(w_{i,j}\),令\(n=|V|\)\(c=(c_1,c_2,\cdots,c_k)(c_i\in V)\)\(G\)中的一個圈當且僅當\((c_i,c_{i+1})(1\le i\lt k)\)\((c_k,c_1)\)都在\(E\)中,這時稱\(k\)為圈\(c\)的長度同時令\(c_{k+1}=c_1\),并定義圈\(c=(c_1,c_2,\cdots,c_k)\)的平均值為\(\mu(c)=\sum\limits_{i=1}^{k} w_{c_i,c_{i+1}}/k\),即\(c\)上所有邊的權值的平均值。令\(\mu'(c)=Min(\mu(c))\)\(G\)中所有圈\(c\)的平均值的最小值。現在的目標是:在給定了一個圖\(G=(V,E)\)以及\(w:E\rightarrow R\)之后,請求出\(G\)中所有圈\(c\)的平均值的最小值\(\mu'(c)=Min(\mu(c))\)

輸入格式:

第一行2個正整數,分別為\(n\)\(m\),并用一個空格隔開,只用\(n=|V|,m=|E|\)分別表示圖中有\(n\)個點\(m\)條邊。
接下來m行,每行3個數\(i,j,w_{i,j}\),表示有一條邊\((i,j)\)且該邊的權值為\(w_{i,j}\)。輸入數據保證圖\(G=(V,E)\)連通,存在圈且有一個點能到達其他所有點。

輸出格式:

請輸出一個實數\(\mu'(c)=Min(\mu(c))\),要求輸出到小數點后8位。

輸入樣例#1:

4 5
1 2 5
2 3 5
3 1 5
2 4 3
4 1 3

輸出樣例#1:

3.66666667

輸入樣例#2:

2 2
1 2 -2.9
2 1 -3.1

輸出樣例#2:

-3.00000000

說明:

對于100%的數據,\(n\le 3000,m\le 10000,|w_{i,j}| \le 10^7\)



\(solution:\)

這道題要我們求平均值的最小值,所以我們考慮二分答案的可能性,先列出答案的意義:

\(ans=\frac{\sum\limits_{i=1}^{k} w_{c_i,c_{i+1}}}{K}\quad _{(c_{k+1}=c_1)}\)

我們將它轉換一下:

\(ans*k={\sum\limits_{i=1}^{k} w_{c_i,c_{i+1}}}\quad _{(c_{k+1}=c_1)}\)

\(0=\sum\limits_{i=1}^{k} (w_{c_i,c_{i+1}})-ans*k\quad _{(c_{k+1}=c_1)}\)

\(0=\sum\limits_{i=1}^{k}(w_{c_i,c_{i+1}}-ans)\quad _{(c_{k+1}=c_1)}\)

這樣我們發現它已經化成了一個二分答案的常用等式(等式右邊可以\(O(n)\)求出來,且具備單調性)而我們注意到等式左邊為0,所以我們可以二分ans,并將邊權改為\(w_{c_i,c_{i+1}}-mid\) ,然后求負環即可。

為什么可以這樣做呢?這個較地震那一題好講一些,我們當前二分出來的平均值mid,我們將每一條邊的邊權都減去它,如果存在負環,說明這個環上所有邊權實際邊權值加起來的平均值一定小于mid!(這里需要仔細想一下)



\(code:\)

#include<iostream> #include<cstdio> #include<iomanip> #include<algorithm> #include<cstring> #include<cstdlib> #include<ctime> #include<cmath> #include<vector> #include<queue> #include<map> #include<set>#define ll long long #define db double #define inf 0x7fffffff #define rg register intusing namespace std;const db cha=1e-9;struct su{db v;int to,next; }a[10005];bool f; int n,m,top; int tou[3005]; bool vis[3005]; db mid,dis[3005];inline int qr(){char ch;while((ch=getchar())<'0'||ch>'9');int res=ch^48;while((ch=getchar())>='0'&&ch<='9')res=res*10+(ch^48);return res; }inline void add(int x,int y){scanf("%lf",&a[++top].v);a[top].to=y;a[top].next=tou[x];tou[x]=top; }inline void spfa(int i){vis[i]=1;for(rg j=tou[i];j;j=a[j].next){if(dis[a[j].to]>dis[i]+a[j].v-mid){dis[a[j].to]=dis[i]+a[j].v-mid;if(vis[a[j].to])return void(f=1);else spfa(a[j].to);}}vis[i]=0; }inline bool check(){for(rg i=1;i<=n;++i)dis[i]=vis[i]=0;;f=0;for(rg i=1;i<=n&&!f;++i)if(!vis[i])spfa(i);return f; }int main(){freopen("cycle.in","r",stdin);freopen("cycle.out","w",stdout);n=qr(),m=qr();for(rg i=1;i<=m;++i)add(qr(),qr());db l=-1e7,r=1e7;while(l<=r){mid=(l+r)/2;if(check())r=mid-cha;else l=mid+cha;}printf("%.8lf\n",l);return 0; }

轉載于:https://www.cnblogs.com/812-xiao-wen/p/10367943.html

總結

以上是生活随笔為你收集整理的[HNOI2009]最小圈 (二分答案+负环)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。