解题报告
题目:http://poj.org/problem?id=3621
题目大意:在一个有向图中,求一个环,使得这个环上所有点的权值之和比所有边权之和最大,输出比值。
思路:想了很久,但都没能转化成二分答案,判环的思想,最后还是看了别人的思路。
0/1分数规划问题。就此题而言,我们要求的是
∑V[i] / ∑C[i] = ans;
设一个数k
当k<=ans 时 ∑V[i] / ∑C[i] >= k.即∑V[i] – k * ∑C[i] >= 0.
当k> ans时 ∑V[i] / ∑C[i] < k 即 ∑V[i] – k * ∑C[i] < 0;
根据上面两个等式:如果我们以∑V[i] – k * ∑C[i]来代替图中原来的边,那么:
当k<=ans 时,图中就会出现正环,这是我们增大k,当没有正环时,减小k。这样二分便可。但是这里还是有一个问题,就是“当k> ans时 ∑V[i] / ∑C[i] < k 即 ∑V[i] – k * ∑C[i] < 0;
”,那么我们为什么不判当出现负环的时候减小k呢,而没有负环的时候增大k呢?仔细想想,只要有某个环的∑V[i] / ∑C[i]的值很小,那么一个没达到ans的k值就会导致他变成负环。但是这个k却里最终ans还很远。而出现只要k小于最终的ans,那么对于比例最大的那个环,他必然会从出现正环,这才是我们为什么用正环的原因所在,想用负环,只要将边值k * ∑C[i] - ∑V[i]便可。
收获与经验:刚过此题是并没有理解到这些,是在写解题报告是才把正负环搞清楚的。。以后要经常写解题报告了。
AC code:
#include <cstdio>
#include <cstring>
#include <cmath>
#define MAXN 2010
#define MAXM 10010
#define EXP 1e-6
#define INF 21000000
struct NODE{
};
NODE edges[MAXM];
int head[MAXN], gain[MAXN], ad;
void clear(){
}
void insert(int u, int v, int len){
}
int in[MAXN], times[MAXN], stack[MAXN];
double dis[MAXN];
bool SPFA(double k, int n){
}
double slove(int n, int m, int up){
}
int main(){
}