Question link http://vjudge.net/problem/viewProblem.action? Id = 34650
Question:
Given a weighted directed graph with m edges at N points, the minimum average weight is obtained.
Average weight = sum of path weights/number of path Edges
We can find the minimum and maximum values among them, and then find the satisfied point through the second, and then obtain the maximum value as much as possible, because there are two valid decimal places, so we set up
While (La-ST> 0.001)
Finding a satisfied value is to create a negative circle after each line segment in the graph is subtracted from this value. We usually use spfa to determine the negative circle.
This spfa is only used to judge whether it is a shortest path. To prevent multiple connected components, You can traverse the entire graph only from one point, so we put all the nodes in the queue at the very beginning.
The value is set to 0. If there is a negative circle, it will be updated cyclically to find the minimum value. We use the CNT [] array. When a point is accessed more than N times, it indicates that a negative circle appears.
The specific spfa functions are as follows:
bool spfa(){ for(int i=1;i<=n;i++) cnt[i]=0,visit[i]=0; visit[1]=1; queue<int> q; for(int i=1;i<=n;i++) q.push(i),dp[i]=0; while(!q.empty()){ int u=q.front(); visit[u]=0; q.pop(); for(int i=first[u];i!=-1;i=path[i].next){ if(dp[path[i].y]>dp[u]+path[i].d){ dp[path[i].y]=dp[u]+path[i].d; if(!visit[path[i].y]) { q.push(path[i].y); if(++cnt[path[i].y]>n) return true; } } } } return false;}
Every time we subtract a mid value to be found, we must add it back after the judgment to avoid the next unexpected judgment.
The Code is as follows:
1 #include <cstdio> 2 #include <cstring> 3 #include <queue> 4 #include <algorithm> 5 using namespace std; 6 #define N 52 7 int first[N],visit[N],k,cnt[N],n; 8 double dp[N],maxn,minn; 9 struct Path{10 int y,next;11 double d;12 }path[100010];13 14 void add(int a,int b,double c)15 {16 path[k].y=b,path[k].d=c,path[k].next=first[a];17 first[a]=k++;18 }19 20 bool spfa()21 {22 for(int i=1;i<=n;i++) cnt[i]=0,visit[i]=0;23 visit[1]=1;24 queue<int> q;25 for(int i=1;i<=n;i++) q.push(i),dp[i]=0;26 while(!q.empty()){27 int u=q.front();28 visit[u]=0;29 q.pop();30 for(int i=first[u];i!=-1;i=path[i].next){31 if(dp[path[i].y]>dp[u]+path[i].d){32 dp[path[i].y]=dp[u]+path[i].d;33 if(!visit[path[i].y]) {34 q.push(path[i].y);35 if(++cnt[path[i].y]>n) return true;36 }37 }38 }39 }40 return false;41 }42 43 bool findMid(double mid)44 {45 for(int i=0;i<k;i++) path[i].d-=mid;46 bool temp=spfa();47 for(int i=0;i<k;i++) path[i].d+=mid;48 return temp;49 }50 51 int main()52 {53 int T,m,a,b;54 double c,st,la,mid,ans=-1;55 scanf("%d",&T);56 for(int j=1;j<=T;j++){57 memset(first,-1,sizeof(first));58 scanf("%d%d",&n,&m);59 k=0;60 maxn=0,minn=10000005;61 for(int i=0;i<m;i++)62 {63 scanf("%d%d%lf",&a,&b,&c);64 add(a,b,c);65 maxn=max(maxn,c);66 minn=min(minn,c);67 }68 st=minn-1,la=maxn;69 printf("Case #%d: ",j);70 if(!findMid(la+1)){printf("No cycle found.\n");continue;}71 while(la-st>0.001){72 mid=st+(la-st)/2;73 if(findMid(mid)) la=mid;74 else ans=mid,st=mid;75 }76 printf("%.2f\n",ans);77 }78 return 0;79 }View code