poj 3621 二分+spfa判负环
2014-11-09 15:36
387 查看
http://poj.org/problem?id=3621
求一个环的{点权和}除以{边权和},使得那个环在所有环中{点权和}除以{边权和}最大。
0/1整数划分问题
令在一个环里,点权为v[i],对应的边权为e[i],
即要求:∑(i=1,n)v[i]/∑(i=1,n)e[i]最大的环(n为环的点数),
设题目答案为ans,
即对于所有的环都有 ∑(i=1,n)(v[i])/∑(i=1,n)(e[i])<=ans
变形得ans* ∑(i=1,n)(e[i])>=∑(i=1,n)(v[i])
再得 ∑(i=1,n)(ans*e[i]-v[i]) >=0
稍分析一下,就有:
当k<ans时,就存在至少一个环∑(i=1,n)(k*e[i]-v[i])<0,即有负权回路(边权为k*e[i]-v[i]);
当k>=ans时,就对于所有的环∑(i=1,n)(k*e[i]-v[i])>=0,即没有负权回路。
然后我们就可以使新的边权为k*e[i]-v[i],用spfa来判断负权回路,二分ans。
求一个环的{点权和}除以{边权和},使得那个环在所有环中{点权和}除以{边权和}最大。
0/1整数划分问题
令在一个环里,点权为v[i],对应的边权为e[i],
即要求:∑(i=1,n)v[i]/∑(i=1,n)e[i]最大的环(n为环的点数),
设题目答案为ans,
即对于所有的环都有 ∑(i=1,n)(v[i])/∑(i=1,n)(e[i])<=ans
变形得ans* ∑(i=1,n)(e[i])>=∑(i=1,n)(v[i])
再得 ∑(i=1,n)(ans*e[i]-v[i]) >=0
稍分析一下,就有:
当k<ans时,就存在至少一个环∑(i=1,n)(k*e[i]-v[i])<0,即有负权回路(边权为k*e[i]-v[i]);
当k>=ans时,就对于所有的环∑(i=1,n)(k*e[i]-v[i])>=0,即没有负权回路。
然后我们就可以使新的边权为k*e[i]-v[i],用spfa来判断负权回路,二分ans。
#include <iostream> #include <cstdlib> #include <cstdio> #include <queue> #include <cstring> #include <algorithm> #define RD(x) scanf("%d",&x) #define RD2(x,y) scanf("%d%d",&x,&y) #define RD3(x,y,z) scanf("%d%d%d",&x,&y,&z) #define clr0(x) memset(x,0,sizeof(x)) #define clr1(x) memset(x,-1,sizeof(x)) using namespace std; typedef long long LL; const int maxn = 1005,maxm = 105; const double eps = 1e-3; const int inf = 0x7fffffff; int v[maxn]; struct edge{ int v,w,next; edge(){}; edge(int vv,int ww,int nnext):v(vv),w(ww),next(nnext){}; }e[maxn*5]; int head[maxn],vis[maxn],_v[maxn],cnt[maxn],ecnt,n,m; double dist[maxn]; void add(int u,int v,int w) { e[ecnt] = edge(v,w,head[u]); head[u] = ecnt++; } void init() { for(int i = 1;i <= n;++i) RD(_v[i]); ecnt = 0; clr1(head);//判负环的初始化 int u,v,w; while(m--){ RD3(u,v,w); add(u,v,w); } return ; } bool spfa(double mid) { clr0(vis),clr0(cnt); fill(dist,dist + n + 1,inf); dist[1] = 0; queue<int> q; q.push(1); while(!q.empty()){ int u = q.front(); q.pop(); vis[u] = false; cnt[u]++; if(cnt[u] > n) return true; for(int i = head[u];i != -1;i = e[i].next){ int v = e[i].v; double tmp = mid*e[i].w - _v[v];//"边权" if(dist[u] + tmp < dist[v]){ dist[v] = dist[u] + tmp; if(!vis[v]){ vis[v] = true; q.push(v); } } } } return false; } void work() { double l = 0,r = 10000,mid,ans; while(r - l > eps){ mid = (l + r)/2; if(spfa(mid)){ ans = mid; l = mid - 0.000001; }else r = mid + 0.000001; } printf("%.2f\n",ans); } int main() { while(~RD2(n,m)){ init(); work(); } return 0; }
相关文章推荐
- POJ 3621 Sightseeing Cows(01分数规划+二分+spfa判负环)
- poj 3621 二分+spfa判负环
- POJ 3621 (最优比率环 二分+SPFA)
- POJ-3621-01分数规划,spfa判负环
- poj 3621 二分+spfa
- poj 3621 二分+spfa
- poj-3621-Sightseeing Cows-01分数规划+spfa判负环
- poj 3621(参数搜索+二分+spfa负环求解)
- Poj 3621 Sightseeing Cows(二分+负环判断)
- poj 3621 Sightseeing Cows 【最优比例环】 【0-1分数规划 + SPFA判负环】
- POJ 3621-Sightseeing Cows-最优比率环|SPFA+二分
- POJ 3662 Telephone Lines 电话线(二分答案+SPFA)
- Poj(3259),SPFA,判负环
- POJ 3259——Wormholes——————【最短路、SPFA、判负环】
- poj 3259 Wormholes (spfa判负环)
- POJ 3621(0/1分数规划,二分) Sightseeing Cows
- POJ 3621 最优比率生成环 二分求解
- POJ 2175 Evacuation Plan (费用流,负环,消圈法,SPFA)
- [POJ 3662] Telephone Lines (二分答案+SPFA)
- poj 3621(参数搜索 + spfa)