zoukankan      html  css  js  c++  java
  • 【BZOJ 1486】 [HNOI2009]最小圈

    【链接】 我是链接,点我呀:)
    【题意】

    在这里输入题意

    【题解】

    我们可以只想那个均值最小的环。

    我们不知道那个环由哪些边构成
    但我们可以把每条边都减掉mid
    那个环受到的影响是什么呢?

    如果这个均值最小的环的均值没有mid那么大。
    那么这个环就会变成负权环(因为(环的均值<mid那么,环的均值*环的大小=这个环的边权和<mid*环大小))。
    如果平均值比mid大
    那么减掉之后显然是不会变成负权环的。
    由于这个环是最小环那么其他的环也不会变成负权环。
    因此。我们可以根据是否出现了负权环。来修改这个mid的值。
    显然有单调性。那么二分答案即可。

    判负权环的时候用了黑科技
    dfs版的spfa..
    每次优先找负权的边。
    然后从那个边的起点开始进行spfa.
    走的路上不断标记某个点是否走过。
    然后如果松弛条件满足。
    且目标点已经走过。
    那么就说明找到了一个环。

    【代码】

    #include <bits/stdc++.h>
    #define LL long long
    #define rep1(i,a,b) for (int i = a;i <= b;i++)
    #define rep2(i,a,b) for (int i = a;i >= b;i--)
    #define all(x) x.begin(),x.end()
    #define pb push_back
    #define lson l,mid,rt<<1
    #define rson mid+1,r,rt<<1|1
    using namespace std;
    
    const double pi = acos(-1);
    const int dx[4] = {0,0,1,-1};
    const int dy[4] = {1,-1,0,0};
    const int N = 3000;
    
    int n,m;
    vector<pair<int,double> > g[N+10];
    double dis[N+10];
    bool vis[N+10],flag;
    
    void dfs(int x,double delta){
        vis[x] = 1;
        for (int i = 0;i < (int)g[x].size();i++){
            pair<int,double> temp = g[x][i];
            int y = temp.first;double cost = temp.second-delta;
            if (dis[y]>dis[x]+cost){
                if (vis[y]||flag){
                    flag = true;
                    break;
                }else{
                    dis[y] = dis[x]+cost;
                    dfs(y,delta);
                }
            }
        }
        vis[x] = 0;
    }
    
    bool ok(double delta){
        for (int i = 1;i <= n;i++) dis[i] = 0;
        flag = false;
        for (int i = 1;i <= n;i++)
            if (dis[i]==0){
                dfs(i,delta);
            }
        return flag;
    }
    
    int main(){
    	#ifdef LOCAL_DEFINE
    	    freopen("rush_in.txt", "r", stdin);
    	#endif
    	ios::sync_with_stdio(0),cin.tie(0);
        cin >> n >> m;
        for (int i = 1;i <= m;i++){
            int x,y;double z;
            cin >> x >> y >> z;
            g[x].push_back(make_pair(y,z));
        }
    
        double l = -1e7-10,r = 1e7+10,temp = 0.0;
        for (int i = 1;i <= 100;i++){
            double mid = (l+r)/2.0;
            if (!ok(mid)){
                temp = mid;
                l = mid;
            }else{
                r = mid;
            }
        }
        cout<<fixed<<setprecision(8)<<temp<<endl;
    	return 0;
    }
    
    
  • 相关阅读:
    神经网络
    密度峰值聚类
    kylin从入门到实战:实际案例
    [时间序列分析][3]--自相关系数和偏自相关系数
    时间序列分析之指数平滑法(holt-winters及代码)
    时间序列模型
    python3.5如何安装statsmodels包?
    时间序列分析和预测
    Xshell6和Xftp6 破解免安装版,无窗口多开限制
    优化问题
  • 原文地址:https://www.cnblogs.com/AWCXV/p/9143218.html
Copyright © 2011-2022 走看看