一、生成树型
给定一个带权无向图,每条边有两个权值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