【POJ3621】Sightseeing Cows 分数规划
【POJ3621】Sightseeing Cows
题意:在给定的一个图上寻找一个环路,使得总欢乐值(经过的点权值之和)/ 总时间(经过的边权值之和)最大。
题解:显然是分数规划,二分答案ans,将每条边的权值变成(ans*边权-2*起始点点权),然后我们希望找出一个环,使得环上的总边权<0
(一开始我把题意理解错了,题中给的是单向边,我把它当成是双向边+每条边只能走一次了~,想出一堆做法都接连pass掉)
然后就直接用SPFA判负环就好了嘛!由于原图不一定联通,所以一开始就把所有点都入队就完事了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | #include <cstdio> #include <iostream> #include <queue> #include <cstring> using namespace std; int n,m,cnt; int f[1010],to[10010],next[10010],head[1010]; int pa[5010],pb[5010],pt[5010],len[1010],inq[1010]; double dis[1010],val[10010]; queue< int > q; void add( int a, int b, double c) { to[cnt]=b,val[cnt]=c,next[cnt]=head[a],head[a]=cnt++; } int solve( double sta) { memset(head,-1, sizeof (head)); memset(len,0, sizeof (len)); cnt=0; int i,u; for (i=1;i<=m;i++) add(pa[i],pb[i],sta*pt[i]-f[pa[i]]); while (!q.empty()) q.pop(); for (i=1;i<=n;i++) q.push(i),dis[i]=0.0,len[i]=1; while (!q.empty()) { u=q.front(),q.pop(),inq[u]=0; for (i=head[u];i!=-1;i=next[i]) { if (dis[to[i]]>dis[u]+val[i]+1e-4) { dis[to[i]]=dis[u]+val[i]; len[to[i]]=len[u]+1; if (len[to[i]]>n) return 1; if (!inq[to[i]]) { inq[to[i]]=1; q.push(to[i]); } } } } return 0; } int main() { scanf( "%d%d" ,&n,&m); int i,a,b,c; double l=0.0,r=0.0,mid; for (i=1;i<=n;i++) scanf( "%d" ,&f[i]),r=max(r,1.0*f[i]); for (i=1;i<=m;i++) scanf( "%d%d%d" ,&pa[i],&pb[i],&pt[i]); while (r-l>1e-4) { mid=(l+r)*0.5; if (solve(mid)) l=mid; else r=mid; } printf( "%.2f" ,l); return 0; } |
| 欢迎来原网站坐坐! >原文链接<
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步