1. 程式人生 > >2月4日 考試——遲到的 ACX

2月4日 考試——遲到的 ACX

ace line -s int class __line__ space sin 其中

                    遲到的 ACX
                    時限:1s
                  內存限制:128MB
題目描述:
  今天長沙下雪了,小 ACX 在上學路上欣賞雪景,導致上學遲到,憤怒的佘總給 ACX 巨佬出了一個題目想考考
他,現在他找到你,希望你能幫幫他。
對於一張有向圖,要你求圖中最小環的平均值最小是多少,即若一個環經過 k 個節點,那麽這個環的平均值為
環上 k 條邊權的和除以 k,現要求其中的最小值。
考慮到在座的各位都是巨佬,本題需要保留小數點後面八位。
讀入格式:
  第一行 2 個正整數,分別為 n 和 m ,並用一個空格隔開,分別表示圖中有 n 個點 m 條邊。 接下來 m 行,


每行 3 個數 i,j,w 表示有一條邊(i,j)且該邊的權值為 w。輸入數據保證圖連通,存在環且有一個點能到達其他所有
點。
輸出格式:
  請輸出一個實數及最小環的平均值,要求輸出到小數點後 8 位。
樣例輸入:
4 5
1 2 5
2 3 5
3 1 5
2 4 3
4 1 3
樣例輸出:
3.66666667
數據範圍:
100%的數據: n<=3000 m<=10000 |wi,j|<=10^7

Solution:

  看到這題一個很好的思路就是二分答案,把問題轉化成判定性問題。二分答案後,將每條邊的邊權都減去答案Ans,那麽問題就轉變成了判定一幅圖中是否存在負環,一個經典的做法就是用Spfa,判斷一個點有沒有被加入超過N次,如果有則存在負環,可是這個復雜度是O(NM)的,不能通過本題。還有一種判負環的思想就是用Dfs來跑Spfa,然後一個點重復出現時就存在負環。具體實現可以一開始把所有點的初始距離設為0,然後枚舉以每個點位開頭是否存在負環,因為一個負環總有一個位置開始到每個點的路徑都是負數。用這種做法就可以通過本題了。

代碼:

  

 1 /*本題不要想歪,直接二分+spfa,不多bb——by 520*/
 2 #include<bits/stdc++.h>
 3 #define il inline 
 4 #define ll long long 
 5 #define debug printf("%d %s\n",__LINE__,__FUNCTION__)
 6 using namespace std;
 7 int n,m,cnt,h[3020];
 8 double dis[3020],ans;
 9 struct edge{
10     int to,net;double
val; 11 }e[52000]; 12 bool vis[3020],bj; 13 il void add(int u,int v,double w) 14 { 15 e[++cnt].net=h[u],h[u]=cnt,e[cnt].to=v,e[cnt].val=w; 16 } 17 il void spfa(int x) 18 { 19 vis[x]=1; 20 for(int i=h[x];i;i=e[i].net){ 21 int v=e[i].to; 22 if(dis[x]+e[i].val-ans<dis[v]){ 23 if(vis[v]){ bj=1;return;} 24 dis[v]=dis[x]+e[i].val-ans; 25 spfa(v); 26 if(bj)return; 27 } 28 } 29 vis[x]=0; 30 } 31 il bool check() 32 { 33 memset(dis,0,sizeof(dis)); 34 memset(vis,0,sizeof(vis)); 35 for(int i=1;i<=n;i++){ 36 bj=0;spfa(i); 37 if(bj)return 1; 38 } 39 return 0; 40 } 41 int main() 42 { 43 freopen("late.in","r",stdin); 44 freopen("late.out","w",stdout); 45 scanf("%d%d",&n,&m); 46 int u,v;double w; 47 for(int i=1;i<=m;i++)scanf("%d%d%lf",&u,&v,&w),add(u,v,w); 48 double l=-2333333,r=2333333; 49 while(r-l>1e-9){ 50 ans=(l+r)/2; 51 if(check())r=ans; 52 else l=ans; 53 } 54 printf("%.8lf",ans); 55 return 0; 56 }

2月4日 考試——遲到的 ACX