训练指南 UVA- 11865(有向最小生成树 + 朱刘算法 + 二分)



layout: post
title: 训练指南 UVA- 11865(有向最小生成树 + 朱刘算法 + 二分)
author: "luowentaoaa"
catalog: true
mathjax: true
tags:
- 最小生成树
- 图论
- 训练指南


Stream My Contest

UVA - 11865

二分带宽,然后判断最小生成树是否小于cost值。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=998244353;
const int maxn=100+50;
const ll inf=1000000000;;

/// 固定根的最小树型图,邻接矩阵写法
struct MDST{
    int n;
    int w[maxn][maxn];    ///边权
    int vis[maxn];        ///访问标记,仅用来判断无解
    int ans;              ///计算答案
    int removed[maxn];    ///每个点是否被删除
    int cid[maxn];        ///所在圈编号
    int pre[maxn];        ///最小入边的起点
    int iw[maxn];         ///最小入边的权值
    int max_cid;          ///最大圈编号

    void init(int n){
        this->n=n;
        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++)w[i][j]=inf;
    }
    void AddEdge(int u,int v,int cost){
        w[u][v]=min(w[u][v],cost);  ///重边取权值最小的
    }

    ///从s出发能到达多少个结点
    int dfs(int s){
        int ans=1;
        vis[s]=1;
        for(int i=0;i<n;i++)if(!vis[i]&&w[s][i]<inf)ans+=dfs(i);
        return ans;
    }
    ///从u出发沿着pre指针找圈
    bool cycle(int u){
        max_cid++;
        int v=u;
        while(cid[v]!=max_cid){cid[v]=max_cid;v=pre[v];}
        return v==u;
    }
    /// 计算u的最小入弧,入弧起点不得在圈c中
    void update(int u){
        iw[u]=inf;
        for(int i=0;i<n;i++)
        if(!removed[i]&&w[i][u]<iw[u]){
            iw[u]=w[i][u];
            pre[u]=i;
        }
    }
    ///根节点为s,如果失败返回false
    bool solve(int s){
        memset(vis,0,sizeof(vis));
        if(dfs(s)!=n)return false;
        memset(removed,0,sizeof(removed));
        memset(cid,0,sizeof(cid));
        for(int u=0;u<n;u++)update(u);
        pre[s]=s;iw[s]=0;      /// 根结点特殊处理
        ans=max_cid=0;
        for(;;){
            bool have_cycle=false;
            for(int u=0;u<n;u++)if(u!=s&&!removed[u]&&cycle(u)){
                have_cycle=true;
                /// 以下代码缩圈,圈上除了u之外的结点均删除
                int v=u;
                do{
                    if(v!=u)removed[v]=1;
                    ans+=iw[v];
                    /// 对于圈外点i,把边i->v改成i->u(并调整权值);v->i改为u->i
                    /// 注意圈上可能还有一个v'使得i->v'或者v'->i存在,因此只保留权值最小的i->u和u->i
                    for(int i=0;i<n;i++)if(cid[i]!=cid[u]&&!removed[i]){
                        if(w[i][v]<inf)w[i][u]=min(w[i][u],w[i][v]-iw[v]);
                        w[u][i]=min(w[u][i],w[v][i]);
                        if(pre[i]==v)pre[i]=u;
                    }
                    v=pre[v];
                }while(v!=u);
                update(u);
                break;
            }
            if(!have_cycle)break;
        }
        for(int i=0;i<n;i++)
            if(!removed[i])ans+=iw[i];
        return true;
    }
};
MDST solver;
struct Edge{
    int u,v,b,c;
    bool operator <(const Edge& rhs)const{
        return b>rhs.b;
    }
};
const int maxm=10000+10;
int n,m,C;
Edge edges[maxm];
bool check(int cnt){
    solver.init(n);
    for(int i=0;i<cnt;i++)
        solver.AddEdge(edges[i].u,edges[i].v,edges[i].c);
    if(!solver.solve(0))return false;
    return solver.ans<=C;
}
int main()
{
    std::ios::sync_with_stdio(false);
    std::cin.tie(0);
    std::cout.tie(0);
    int t;
  /*  int a=inf;
    cout<<a<<endl<<1000000000<<endl;*/
    cin>>t;
    while(t--){
        cin>>n>>m>>C;
        for(int i=0;i<m;i++)cin>>edges[i].u>>edges[i].v>>edges[i].b>>edges[i].c;
        sort(edges,edges+m);
        int l=1,r=m,ans=-1;
        while(l<=r){
            int mid=(l+r)/2;
            if(check(mid)){ans=edges[mid-1].b;r=mid-1;}
            else l=mid+1;
        }
        if(ans<0)cout<<"streaming not possible."<<endl;
        else cout<<ans<<" kbps"<<endl;
    }
    return 0;
}

原文地址:https://www.cnblogs.com/luowentao/p/10350668.html

时间: 2024-09-30 19:28:58

训练指南 UVA- 11865(有向最小生成树 + 朱刘算法 + 二分)的相关文章

UVA-11865 Stream My Contest (朱-刘 算法+二分)

题目大意:有一张n个顶点,m条边的有向图,根节点为0.每条边有两个权值,一个是费用c,一个是长度b.问在总费用不超过cost的情况下选出若干条边,使得n个点连通时的边的最短长度的最大值是多少. 题目分析:如果已知这个最短距离的最大值d,则问题就变成了:用长度不小于d的边能否构成一个总权值不大于cost的最小树形图.因此,二分枚举d,用朱-刘 算法判断即可. 代码如下: # include<iostream> # include<cstdio> # include<vector

Uva11183-Teen Girl Squad(有向图最小生成树朱刘算法)

解析: 裸的有向图最小生成树 代码 #include<cstdio> #include<cstring> #include<string> #include<iostream> #include<sstream> #include<algorithm> #include<utility> #include<vector> #include<set> #include<map> #incl

训练指南 UVA - 11354(最小生成树 + 倍增LCA)

layout: post title: 训练指南 UVA - 11354(最小生成树 + 倍增LCA) author: "luowentaoaa" catalog: true mathjax: true tags: - 最小生成树 - LCA - 图论 - 训练指南 Bond UVA - 11354 题意 给你一张无向图,然后有若干组询问,让你输出a->b的最小瓶颈路 题解 先求出最小生成树,然后对这个最小生成树做LCA. #include<bits/stdc++.h>

训练指南 UVA - 11374(最短路Dijkstra + 记录路径 + 模板)

layout: post title: 训练指南 UVA - 11374(最短路Dijkstra + 记录路径 + 模板) author: "luowentaoaa" catalog: true mathjax: true tags: - 最短路 - Dijkstra - 图论 - 训练指南 Airport Express UVA - 11374 题意 机场快线有经济线和商业线,现在分别给出经济线和商业线的的路线,现在只能坐一站商业线,其他坐经济线,问从起点到终点的最短用时是多少,还有

训练指南 UVA - 10917(最短路Dijkstra + 基础DP)

layout: post title: 训练指南 UVA - 10917(最短路Dijkstra + 基础DP) author: "luowentaoaa" catalog: true mathjax: true tags: - 最短路 - 基础DP - Dijkstra - 图论 - 训练指南 Walk Through the Forest UVA - 10917 题意 Jimmy打算每天沿着一条不同的路走,而且,他只能沿着满足如下条件的道路(A,B):存在一条从B出发回家的路径,比

训练指南 UVA - 11090(最短路BellmanFord+ 二分判负环)

layout: post title: 训练指南 UVA - 11090(最短路BellmanFord+ 二分判负环) author: "luowentaoaa" catalog: true mathjax: true tags: - 最短路 - 基础DP - BellmanFord - 图论 - 训练指南 Going in Cycle!! UVA - 11090 题意 就最小的环的平均权值 题解 分枚举平均值mid,只需判断是否存在平均值小于mid的回路,即判断是否有sum(wi)&

训练指南 UVA - 11478(最短路BellmanFord+ 二分+ 差分约束)

layout: post title: 训练指南 UVA - 11478(最短路BellmanFord+ 二分+ 差分约束) author: "luowentaoaa" catalog: true mathjax: true tags: - 最短路 - BellmanFord - 图论 - 训练指南 - 差分约束 Halum UVA - 11478 题意 带权有向图,每个点都可以有如下操作:令从ta出发的每一条边增加d,终止于ta的每一条边减小d 最后让所有边权的最小值非负且尽量大 题

训练指南 UVA - 11383(KM算法的应用 lx+ly &gt;=w(x,y))

layout: post title: 训练指南 UVA - 11383(KM算法的应用 lx+ly >=w(x,y)) author: "luowentaoaa" catalog: true mathjax: true tags: - KM算法 - 训练指南 Golden Tiger Claw UVA - 11383 题意 给一个n*n的矩阵,每个格子中有正整数w[i[j],试为每行和每列分别确定一个数字row[i]和col[i],使得任意格子w[i][j]<=row[i

训练指南 UVA - 11419(二分图最小覆盖数)

layout: post title: 训练指南 UVA - 11419(二分图最小覆盖数) author: "luowentaoaa" catalog: true mathjax: true tags: - 二分图 - 最小点覆盖 - 图论 - 训练指南 SAM I AM UVA - 11419 题目大意:给出一个R×C的网格,网格上棉纺了一些目标.可以在网格外发射子弹,子弹会沿着垂直或水平方向飞行,并且打掉飞行路径上的所有目标.你的任务是计算出最少需要多少子弹,各从哪个位置发射,才