01分数规划三类型总结

一、生成树型

给定一个带权无向图,每条边有两个权值a[i],b[i],求图的一个生成树,使得sigam(a[i])/sigam(b[i])最小.


解析:我们假设已经找到了一个解k,一个新的解比k更优

那么sigam(a[i])/sigam(b[i])<=k

即sigam(a[i])-k*sigam(b[i])<=0

sigam(a[i]-k*b[i])<=0

然后我们只需要求不等式左边的sigam(a[i]-b[i])的最小值ans,比较ans和0的关系就能判断当前解是否最优。


那么我们算法的流程就是这样了:

(1)二分一个k

(2)用新的边权a[i]-k*b[i]建图

(3)求最小生成树

(4)判断当前解是否最优


例:【jzyzoj1636】老司机飙车

现在有N个群需要张锳杰老司机的资源,为了方便表示,我们用1到N这N个数字来表示这N个群。张锳杰现在在群1,而由于网警的原因,在每个群之间传输资源都有特定的需要耗费的时间和所承担的危险,而且同一时间内资源只能在两个群之间传递。为了凸显程序员的逼格,我们将每个群在一个三维空间内以坐标的形式表示,定义两个群之间传输资源所需时间为这两个群在xOy平面内投影的直线距离,而危险则被定义为两个群第三维坐标之差。张锳杰想要单位时间内的平均危险最小,也就是传输总时间与承担的总危险的比值最低,请你帮老司机找出这个比值

#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define eps 0.0005
#define FILE "read"
#define MAXN 1010
#define up(i,j,n) for(int i=j;i<=n;i++)
#define dn(i,j,n) for(int i=j;i>=n;i--)
namespace INIT{
	char buf[1<<15],*fs,*ft;
	inline char getc(){return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;}
	inline int read(){
		int x=0,f=1;  char ch=getc();
		while(!isdigit(ch))  {if(ch=='-')  f=-1;  ch=getc();}
		while(isdigit(ch))  {x=x*10+ch-'0';  ch=getc();}
		return x*f;
	}
}using namespace INIT;
struct node{
	int x,y,h;double v;
	bool operator<(const node pp) const {return v


二、最小割型

给定一个带权无向图,要使得从S到T没有路径相连,需要删除C条边,求这C条边的权值和sigam(vi)/C的最小值。


解析:与上题一样,我们还是假设已经找到了一个解k,那么一个更优解需要满足的条件是sigam(vi)/C<=k

即sigam(vi)-C*k<=0

sigam(vi-k)<=0

那么我们只需要求出不等式左边的最小值,判断它与0的关系就行了。


那么算法的流程如下:

(1)二分一个k值

(2)用新的边权vi-k建图

(3)跑最小割

(4)判断当前解是否最优

#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define FILe "read"
#define INF 1000000000
#define eps 0.00001
#define MAXM 4050
#define MAXN 1050
#define up(i,j,n) for(int i=j;i<=n;i++)
#define dn(i,j,n) for(int i=j;i>=n;i--)
const double oo=9999999999999ll;
namespace INIT{
	char buf[1<<15],*fs,*ft;
	inline char getc(){return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;}
	inline int read(){
		int x=0,f=1;  char ch=getchar();
		while(!isdigit(ch))  {if(ch=='-')  f=-1;  ch=getchar();}
		while(isdigit(ch))  {x=x*10+ch-'0';  ch=getchar();}
		return x*f;
	}
}using namespace INIT;
struct node{int x,y,next,rel;double v;}e[MAXM*4];
int n,m,len,top,Link[MAXN],q[MAXN],level[MAXN],X[MAXN],Y[MAXN],V[MAXN],stack[MAXN],col[MAXN],vis[MAXN];\
bool comp(double a,double b){return abs(a-b)=0;
}
double MAXFLOW(int x,double flow){
	if(x==n)  return flow;
	double maxflow=0,d=0;
	for(int i=Link[x];i&&maxflow



你可能感兴趣的:(01分数规划三类型总结)