zoukankan      html  css  js  c++  java
  • 训练指南 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;
    }
    
  • 相关阅读:
    UV动画
    使用RampTexture实现BRDF效果
    使用RampTexture来控制diffuse shading
    Half Lambert
    Lamber算法 & SurfaceShader自定义光照
    What is _MainTex_ST ?
    C# Enum,Int,String的互相转换
    Plugins in Unity
    Mono在Full AOT模式下的限制
    雾化
  • 原文地址:https://www.cnblogs.com/luowentao/p/10350668.html
Copyright © 2011-2022 走看看