关于精度问题
  • 板块学术版
  • 楼主Durancer
  • 当前回复1
  • 已保存回复1
  • 发布时间2021/1/20 11:06
  • 上次更新2023/11/5 04:38:42
查看原帖
关于精度问题
230804
Durancer楼主2021/1/20 11:06

一个用二分答案,找一个环的问题 因为有负数,一开始怕负数会影响答案(其实并不影响),所以给每条边都 + + 上了边权值的最大值,但是最后求出来的答案精度会有所偏差,为什么? 附上两份代码(一个正常,一个加上 maxmax)和样例

2 2
1 2 -2.9
2 1 -3.1
/*

	简化题意,给定带权有向图,求平均边权(总边权/边数)最小的环。
	一脸疑惑の看了半天式子, 
	为什么+1e7 之后 减去 1e7 不行=_= 
	精度不够! 
*/

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<stack>
#include<map>
#include<algorithm>
#include<cmath>
#include<vector>
using namespace std;
const double lim=1e-10;
const int M=1e5+9;
struct node{
	int last;
	int to;
	double dis;
}e[M<<1];
int head[M],cnt;
double ans;
double dis[M];
int vis[M];
int n,m;
void add(int from,int to,double dis)
{
	e[++cnt].last=head[from];
	e[cnt].to=to;
	e[cnt].dis=dis;
	head[from]=cnt;
}
void clear()
{
	for(int i=1;i<=n;i++)
		dis[i]=vis[i]=0;
}
bool search(int u,double x)
{
	vis[u]=true;
	for(int i=head[u];i;i=e[i].last)
	{
		int v=e[i].to;
		double w=e[i].dis;
		if(dis[v]>dis[u]+w-x)
		{
			dis[v]=dis[u]+w-x;
			if(vis[v]) return true;
			if(search(v,x)) return true;
		} 
	}
	vis[u]=false;
	return false;
}
bool check(double x)
{
	clear();
	for(int i=1;i<=n;i++)
		if(search(i,x)) return true;
	return false;//一个else 毁全家 
}

int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=m;i++)
	{	
		int x,y;
		double z;
		scanf("%d%d%lf",&x,&y,&z);
		add(x,y,z);
	}
	double l=-1e7+9,r=1e7+9;
	while(r-l>=lim)
	{
		double mid=(l+r)/2.0;
		if(check(mid))
		{
			ans=mid;
			r=mid;
		}
		else l=mid;
	}
	printf("%.8lf",ans);
	return 0;
}
/*

    简化题意,给定带权有向图,求平均边权(总边权/边数)最小的环。
    一脸疑惑の看了半天式子,

*/

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <stack>
#include <map>
#include <algorithm>
#include <cmath>
#include <vector>
using namespace std;
const double lim = 1e-6;
const int N = 3e3 + 9;
const int M = 1e4 + 9;
struct node {
    int last;
    int to;
    double dis;
} e[M * 2];
int head[N], cnt;
double ans;
double dis[N];
int vis[N];
int n, m;
void add(int from, int to, double dis) {
    e[++cnt].last = head[from];
    e[cnt].to = to;
    e[cnt].dis = dis;
    head[from] = cnt;
}
void clear() {
    memset(dis, 0, sizeof(dis));
    memset(vis, 0, sizeof(vis));
}
bool search(int u, double x) {
    vis[u] = true;

    for (int i = head[u]; i; i = e[i].last) {
        int v = e[i].to;
        double w = e[i].dis;

        if (dis[v] > dis[u] + w - x) {
            dis[v] = dis[u] + w - x;

            if (vis[v])
                return true;

            if (search(v, x))
                return true;
        }
    }

    vis[u] = false;
    return false;
}
inline bool check(double x) {
    clear();

    for (int i = 1; i <= n; i++)
        if (search(i, x))
            return true;

    return false;
}

int main() {
    scanf("%d%d", &n, &m);

    for (int i = 1; i <= m; i++) {
        int x, y;
        double z;
        scanf("%d%d%lf", &x, &y, &z);
        add(x, y, z + 1e7);
    }

    double l = 0, r = 2e7;

    while (r - l > lim) {
        double mid = (l + r) / 2.0;

        if (check(mid)) {
            ans = mid;
            r = mid - lim;
        } else
            l = mid + lim;
    }

    printf("%.8lf", (ans - 10000000 * 1.0));
    return 0;
}
2021/1/20 11:06
加载中...