zoukankan      html  css  js  c++  java
  • POJ3621 Sightseeing Cows(最优比率环)

    题目链接:http://poj.org/problem?id=3621

    在一个有向图中选一个环,使得环上的点权和除以边权和最大。求这个比值。

    经典的分数规划问题,我认为这两篇题解写得非常清楚,能够參考一下http://blog.csdn.net/gengmingrui/article/details/47443705http://blog.csdn.net/wall_f/article/details/8221807

    个人认为01分数规划差点儿都是二分或者迭代比值,从而找到一个最优解,使得原来的函数值等于0

    #include<cstdio>
    #include<cstring>
    #include<queue>
    #define eps 1e-3
    #define MAXN 1010
    using namespace std;
    struct T
    {
    	int v;
    	int w;
    	int next;
    }edge[5005];
    int cnt,head[MAXN];
    void add_edge(int u,int v,int w)
    {
    	edge[cnt].v = v;
    	edge[cnt].w = w;
    	edge[cnt].next = head[u];
    	head[u] = cnt++;
    }
    int n,m;
    int w[MAXN];
    double dis[MAXN];
    bool inque[MAXN];
    int vis[MAXN];
    bool SPFA(double R)//SPFA推断负权环
    {
    	queue<int> myque;
    	memset(inque,0,sizeof inque);
    	memset(vis,0,sizeof vis);
    	for(int i = 1; i <= n; i++)
    		dis[i] = 1e15;
    	myque.push(1);
    	dis[1] = 0;
    	inque[1] = 1;
    	vis[1]++;
    	while(!myque.empty())
    	{
    		int u = myque.front();
    		myque.pop();
    		inque[u] = 0;
    		for(int i = head[u]; i != -1; i = edge[i].next)
    		{
    			int v = edge[i].v;
    			int y = edge[i].w;
    			if(dis[u] + R*y - w[u] < dis[v])
    			{
    				dis[v] = dis[u] + R*y - w[u];
    				if(!inque[v])
    				{
    					myque.push(v);
    					inque[v] = 1;
    					vis[v]++;
    					if(vis[v] > n) return 1;
    				}
    			}
    		}
    	}
    	return 0;
    }
    int main()
    {
    	memset(head,-1,sizeof head);
    	scanf("%d%d",&n,&m);
    	for(int i = 1; i <= n; i++)
    		scanf("%d",&w[i]);
    	for(int i = 1; i <= m; i++)
    	{
    		int a,b,c;
    		scanf("%d%d%d",&a,&b,&c);
    		add_edge(a,b,c);
    	}
    	double l = 0,r = 10000,mid;
    	while(r - l > eps)
    	{
    		mid = (l+r)/2;
    		if(SPFA(mid)) l = mid;//因为我们是把权值取反了的。因此题解中的R过大变成了R过小
    		else r = mid;
    	}
    	printf("%.2lf
    ",l);
    	return 0;
    }


  • 相关阅读:
    oracle DBA 常用表和视图
    oracle 索引聚簇表的工作原理
    二进制手表
    二分查找
    二分查找
    排列硬币
    将每个元素替换为右侧最大元素
    搜索插入位置----二分查找
    合并两个有序数组
    在Nuxt遇到的坑
  • 原文地址:https://www.cnblogs.com/zsychanpin/p/6972607.html
Copyright © 2011-2022 走看看