(最优比例环)POJ 3621 - Sightseeing Cows
题意:
在一个有向加权图中找到一个环,使这个环点权和/边权和 最大
分析:
一开始还没做过最优比率生成树,但是看到过,两题都A不了。
后来看了题解,索性一起撸掉。
这题可以用类似最优比率生成树的方法做,二分答案。
具体: 这个题解讲的很详细了。
代码:
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <vector> 5 #include <queue> 6 7 8 using namespace std; 9 10 const int inf=0x3f3f3f3f; 11 const int maxn=1010; 12 13 #define eps (1e-6) 14 15 int sgn(double x) { 16 return x<-eps?-1:x>eps?1:0; 17 } 18 19 int n,m; 20 21 bool vis[maxn]; 22 int cnt[maxn]; 23 int val[maxn]; 24 double dist[maxn]; 25 26 struct Edge { 27 int v; 28 double cost; 29 Edge(int _v=0,double _cost=0.0) { 30 v=_v; 31 cost=_cost; 32 } 33 }; 34 35 vector<Edge> edge[maxn]; 36 37 38 bool SPFA(double rate) { 39 memset(vis,0,sizeof(vis)); 40 memset(cnt,0,sizeof(cnt)); 41 memset(dist,0,sizeof(dist)); 42 queue<int> q; 43 while(!q.empty())q.pop(); 44 for(int i=1; i<=n; i++) { 45 dist[i]=0; 46 vis[i]=1; 47 cnt[i]=1; 48 q.push(i); 49 } 50 while(!q.empty()) { 51 int u = q.front(); 52 q.pop(); 53 vis[u]=false; 54 for(int i=0; i<edge[u].size(); i++) { 55 int v= edge[u][i].v; 56 double w=edge[u][i].cost*rate-val[v]; 57 if(dist[v]>dist[u]+w) { 58 dist[v]=dist[u]+w; 59 if(!vis[v]) { 60 vis[v]=true; 61 q.push(v); 62 if(++cnt[v]>n)return false; 63 } 64 } 65 } 66 } 67 return true; 68 } 69 70 71 int main() { 72 while(~scanf("%d%d",&n,&m)) { 73 for(int i=1; i<=n; i++) { 74 scanf("%d",&val[i]); 75 edge[i].clear(); 76 } 77 for(int i=0; i<m; i++) { 78 int u,v; 79 double c; 80 scanf("%d%d%lf",&u,&v,&c); 81 edge[u].push_back(Edge(v,c)); 82 } 83 double left=0; 84 double right=1000; 85 while(sgn(left-right)<0) { 86 double mid=(left+right)/2; 87 if(!SPFA(mid)) { 88 left=mid; 89 } else { 90 right=mid; 91 } 92 } 93 printf("%.2f\n",left); 94 } 95 return 0; 96 97 }