• 267C


    二分+高斯消元

    我们利用物理里的势能来表示,每个点有一个势能h,再由流量守恒可以得到deg[x]*h[x]=sigma(h[y]) 如果x,y之间有边。这个式子是由流量守恒推出的,所以当x=1或n是不满足这个方程的。

    每次二分n的势能,然后把1和n赋值,高斯消元,检验答案。

    势能保证了到达一个点所有路径长度相同,也保证了流量守恒。

    各种小错误 调了两个小时

    #include<bits/stdc++.h>
    using namespace std;
    const int N = 110;
    struct edge {
        int a, b;
        double c;
    } e[N * 100];
    int n, m;
    double ans;
    double a[N][N];
    void gauss()
    {
        for(int i = 1; i <= n; ++i)
        {
            int now = i, pos = i;
            while(now <= n) 
            {
                if(fabs(a[now][i]) > fabs(a[pos][i]))
                    pos = now;
                ++now;
            }
            for(int j = 1; j <= n + 1; ++j)
                swap(a[i][j], a[pos][j]);
            if(fabs(a[i][i]) < 1e-10) continue;
            double x = a[i][i];
            for(int j = 1; j <= n + 1; ++j)
                a[i][j] /= x;
            for(int j = 1; j <= n; ++j) if(j != i && fabs(a[j][i]) > 1e-10)
            {
                double x = a[j][i] / a[i][i];
                for(int k = 1; k <= n + 1; ++k) 
                    a[j][k] -= x * a[i][k]; 
            }
        }
    }
    bool C(double x)
    {
        for(int i = 1; i <= n; ++i)
            for(int j = 1; j <= n + 1; ++j)
                a[i][j] = 0.0;
        for(int i = 1; i <= m; ++i)
        {
            if(e[i].b != 1 && e[i].b != n)
            {
                a[e[i].b][e[i].b] += 1.0;
                a[e[i].b][e[i].a] -= 1.0;
            }
            if(e[i].a != 1 && e[i].a != n)
            {
                a[e[i].a][e[i].a] += 1.0;
                a[e[i].a][e[i].b] -= 1.0;
            }
        }
        a[1][1] = 1.0;
        a[n][n] = 1.0;
        a[n][n + 1] = x;
        gauss();
        for(int i = 1; i <= m; ++i)
        {
            if(fabs(a[e[i].b][n + 1] - a[e[i].a][n + 1]) > e[i].c) return false;
        }
        return true;
    }
    int main()
    {
        scanf("%d%d", &n, &m);
        for(int i = 1; i <= m; ++i)
        {
            scanf("%d%d%lf", &e[i].a, &e[i].b, &e[i].c);
        }
        double l = 0, r = 1e9 + 1;
        while(r - l > 1e-10)
        {
            double mid = (l + r) / 2.0;
            if(C(mid)) l = ans = mid;
            else r = mid;
        }
        C(ans);
        ans = 0;
        for(int i = 1; i <= m; ++i)
        {
            if(e[i].b == n || e[i].a == n) ans += fabs(a[e[i].b][n + 1] - a[e[i].a][n + 1]); 
        }
        printf("%.6f
    ", ans);
        for(int i = 1; i <= m; ++i)
            printf("%.6f
    ", a[e[i].b][n + 1] - a[e[i].a][n + 1]);
        return 0;
    }
    View Code
  • 相关阅读:
    创建一个windows服务的小程序及注意事项
    Asp中上传文件
    C#创建Excel表格(样式设置)
    在Windows服务中使用EventLog组件纪录日志
    MVC中使用 事物
    WCF(学习笔记)【参见WCF教程】
    用vs命令提示符来使用 Installutil.exe来安装和卸载Windows服务
    web service使用注意事项
    iphone开发 有关 Navigation Bar 和 UITableView 的用法(Navigation Bar 的edit 按钮 自定义实现编辑状态)
    在Mvc中 使用 Ajax 提交和接收 数据
  • 原文地址:https://www.cnblogs.com/19992147orz/p/7120156.html
Copyright © 2020-2023  润新知