• POJ 3621 Sightseeing Cows


      http://poj.org/problem?id=3621

      这两天一直在复习代码,因为好久都不写东西了,而且转了语言,除了Dinic我什么都不会写……

      题目大意:给你一个有向图,边有权(T),点有权(F),使求一个环,使得最大化∑(F)/∑(T)。

      这是一个最优比率环问题,与上一个最有比率生成树问题相似,都是01分数规划的考点。

      设 ans≥∑(F)/∑(T) , 有

        ∑(F)-∑(T)*ans≤0

        ∑(F-T*ans)≤0

      我们可以二分ans,将图的边权变为 F-T*ans,用SPFA判断图中是否有负权回路。如果图中有负权回路,则当前回路中 ∑(F)-∑(T)*ans<0,继而推得∑(F)/∑(T)≤ans,为符合条件的解,ans需要向上二分;反之,ans需要向下二分。

      

    难看的代码:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <queue>
    #include <cmath>
    #define DINF 10000000.0
    #define mm 10000
    #define mn 1001
    #define eps 1e-3
    using namespace std;
    
    queue<int> q;
    int x,y,n,m,cnt[mn];
    double dist[mn],F[mn],z;
    bool vis[mn];
    struct EDGE{
    	int pnt;
    	double dist;
    	EDGE *pre;
    	EDGE (){}
    	EDGE(int _pnt,double _dist,EDGE *_pre):pnt(_pnt),dist(_dist),pre(_pre){}
    }Edge[mm],*SP=Edge,*edge[mm];
    
    inline void addedge(int a,int b,double c){
    	edge[a]=new(++SP)EDGE(b,c,edge[a]);
    }
    
    bool SPFA(double ans){
    	memset(cnt,0,sizeof(cnt));
    	for(int i=2;i<=n;i++) dist[i]=DINF;
    	memset(vis,false,sizeof(vis));
    	while(!q.empty()) q.pop();
    	q.push(1);dist[1]=0;
    	while(!q.empty()){
    		int i=q.front();q.pop();vis[i]=false;
    		for(EDGE *j=edge[i];j;j=j->pre)
    			if(dist[j->pnt]>dist[i]+ans*j->dist-F[j->pnt]){
    				dist[j->pnt]=dist[i]+ans*j->dist-F[j->pnt];
    				if(!vis[j->pnt]){
    					vis[j->pnt]=true;
    					if(++cnt[j->pnt]==n) return true;
    					q.push(j->pnt);
    				}
    			}
    	}
    	return false;
    }
    	
    int main(){
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=n;i++) scanf("%lf",&F[i]);
    	for(int i=1;i<=m;i++){
    		scanf("%d%d%lf",&x,&y,&z);
    		addedge(x,y,z);
    	}
    	double low=0,high=DINF;
    	while(high-low>eps){
    		double mid=(low+high)/2.0;
    		if(SPFA(mid)) low=mid;
    		else high=mid;
    	}
    	printf("%.2lf\n",low);
    	return 0;
    }
    

      

  • 相关阅读:
    Linux命令--2
    Linux命令--1
    登陆网页模板
    前端笔记 (2.CSS)
    前端笔记 (1.HTML)
    linux 在执行命令过程中,反单引号(`)这个符号代表的意义为何?
    linux 变量
    Linux文件系统中的inode节点详细介绍
    【Ctrl】 + 【Alt】 + 【F1~F6】 和 【Ctrl】 + 【Alt】 + 【T】打开的终端有什么不同?
    快速建站教程
  • 原文地址:https://www.cnblogs.com/Delostik/p/2119329.html
Copyright © 2020-2023  润新知