Sightseeing Cows POJ - 3621
生活随笔
收集整理的這篇文章主要介紹了
Sightseeing Cows POJ - 3621
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題意:
L個點,P邊的點邊帶權的有向圖,求一個環點權和與邊權和比值的最大值。
題解:
01分數規劃+判負環
詳細看這里
還是套用01分數規劃模型,點權為value[i],邊權為cost[u],一個環為C,問題要求最大化
最小化就是符號倒過來
和之前一樣處理,設當前答案為r,設邊權為dis[i] = r * ∑cost[i] - ∑value[i]
如果r < r *,則說明至少存在一個環,d[i] < 0,也就是存在負權回環,邊權值并不是提前算好,而是在更新路徑的時候從哪個點訪問到這個邊的就將這條邊設為相應點權與邊權的對應值
如果r > r * ,則不存在負環
判負環一半用spfa,方法:一個點不能入隊n次,否則有負環;一條最短路徑長度不能到n,否則有負環。貌似后者更快
代碼:
#include<algorithm> #include<iostream> #include<cstring> #include<cstdio> #include<cmath> using namespace std; #define N 1005 #define E 5005const double eps=1e-6; int n,m,x,y; int tot,point[N],nxt[E],v[E];double c[E]; double val[N],e[E],ans; double dis[N]; int cnt[N];bool vis[N]; int q[N];void add(int x,int y) {++tot; nxt[tot]=point[x]; point[x]=tot; v[tot]=y; } bool spfa() {memset(dis,0,sizeof(dis));memset(vis,0,sizeof(vis));;memset(cnt,0,sizeof(cnt));int head=0,tail=0;for (int i=1;i<=n;++i){vis[i]=1;++cnt[i];q[(++tail)%n]=i;}while (head!=tail){int now=q[(++head)%n];vis[now]=0;for (int i=point[now];i;i=nxt[i])if (dis[v[i]]<dis[now]+c[i]){dis[v[i]]=dis[now]+c[i];if (!vis[v[i]]){vis[v[i]]=1;++cnt[v[i]];if (cnt[v[i]]>n) return true;q[(++tail)%n]=v[i];}}}return false; } bool check(double L) {for (int i=1;i<=tot;++i)c[i]=val[v[i]]-L*e[i];return spfa(); } double find() {double l=0.0,r=1e4,mid,ans=0.0;while (r-l>eps){mid=(l+r)/2.0;if (check(mid)) ans=l=mid;else r=mid;}return ans; } int main() {scanf("%d%d",&n,&m);for (int i=1;i<=n;++i) scanf("%lf",&val[i]);for (int i=1;i<=m;++i){scanf("%d%d%lf",&x,&y,&e[i]);add(x,y);}ans=find();printf("%.2lf\n",ans); }總結
以上是生活随笔為你收集整理的Sightseeing Cows POJ - 3621的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 酸枣芽的功效与作用、禁忌和食用方法
- 下一篇: 藏菖蒲的功效与作用、禁忌和食用方法