uva 11865 (二分+ 最小树形图)

本文介绍了一种基于二分法求解最小费用树形图问题的算法实现,通过不断调整边的费用来找到满足条件的最小费用。该算法利用了 Zhu-Liu 算法作为核心,并结合了 KuangBin 板子进行优化。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

思路: 二分 bit  跑最小树形图是否满足花费的情况。

代码 : 

#include<bits/stdc++.h>

using namespace std;
typedef long long ll;

const int N =65;
const int M =2e4+5;
const ll inf =1e18+5;

ll in[N];
int vis[N],id[N],pre[N];

struct Edge
{
    int u,v,f;
    ll b;
    ll c;
}edge[M],edges[M];

// kuangbin 板子

ll zhuliu(int root,int n,int m)
{
    ll res=0,u,v;

    while(1)
    {

    for(int i=0;i<n;i++) in[i]=inf;
    for(int i=0;i<m;i++){
        if(edges[i].u!=edges[i].v&&edges[i].c<in[edges[i].v])
        {
            in[edges[i].v]=edges[i].c;
            pre[edges[i].v]=edges[i].u;
        }
    }

    for(int i=0;i<n;i++){
        if(root!=i&&in[i]==inf) return -1;
    }

    int cnt=0;
    memset(id,-1,sizeof(id));
    memset(vis,-1,sizeof(vis));
    in[root]=0;

    for(int i=0;i<n;i++)
    {
        res+=in[i];
        v=i;
        while(vis[v]!=i&&id[v]==-1&&v!=root)
        {
            vis[v]=i;
            v=pre[v];
        }
        if(v!=root&&id[v]==-1){
            for(u=pre[v];u!=v;u=pre[u]) id[u]=cnt;
            id[v]=cnt++;
        }
    }

    if(cnt==0) break;

    for(int i=0;i<n;i++){
        if(id[i]==-1) id[i]=cnt++;
    }

    for(int i=0;i<m;)
    {
        v=edges[i].v;
        edges[i].u=id[edges[i].u]; edges[i].v=id[edges[i].v];
        if(edges[i].u!=edges[i].v)
        {
            edges[i++].c-=in[v];
        }
        else swap(edges[i],edges[--m]);
    }
    n=cnt;
    root=id[root];
    }
    return res;
}


int n,m,C;
int B[M];

int jud(ll num)
{
    int tot=0;
    for(int i=0;i<m;i++)
    {
        if(edge[i].b>=num)edges[tot++]=edge[i];
    }

    ll ans=zhuliu(0,n,tot);
    //cout<<"ans "<<ans<<endl;
    if(ans==-1) return 0;
    if(ans>C) return 0;
    return 1;
}

int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d %d %d",&n,&m,&C);
        for(int i=0;i<m;i++){
            scanf("%d %d %lld %lld",&edge[i].u,&edge[i].v,&edge[i].b,&edge[i].c);
            B[i]=edge[i].b;
        }
        sort(B,B+m);
        int tot=unique(B,B+m)-B;

        int l,r,mid;
        l=0; r=tot-1;
        ll ans=-1;
        while(l<=r)
        {
            mid=(l+r)>>1;
            //cout<<"mid "<<mid<<endl;
            if(jud(B[mid])){
               ans=B[mid];
               l=mid+1;
            }
            else r=mid-1;
        }
        if(ans==-1)
        {
            printf("streaming not possible.\n");
        }
        else printf("%lld kbps\n",ans);
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值