• 题解 UVA11865 【Stream My Contest】


    最小树形图(朱刘算法)(+) 二分答案。

    由题意得,我们要在一些有向边中选出一些边,使(0)号节点能够到达其他节点,使距离之和(leqslant cost),并且使每条边中的带宽的最小值最大。

    为方便起见,我将(0 sim n-1)号节点都(++),转为(1 sim n)号节点。

    第一个要求用最小树形图来解决,最小值最大用二分答案来解决,在二分时只选出带宽(geqslant mid)的边,用选出的边求最小树形图,判断二分是否合法。

    多组数据以及二分答案都涉及多次进行朱刘算法,记得清空。

    (code:)

    #include<bits/stdc++.h>
    #define maxn 20010
    #define maxc 1000000
    #define inf 200000000
    using namespace std;
    template<typename T> inline void read(T &x)
    {
    	x=0;char c=getchar();bool flag=false;
    	while(!isdigit(c)){if(c=='-')flag=true;c=getchar();}
    	while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
    	if(flag) x=-x;
    }
    int t,p,q,c,n,m,root,l,r,ans;
    struct edge
    {
        int x,y,v,b;
    }e[maxn],ed[maxn];
    int id[maxn],pre[maxn],ine[maxn],vis[maxn];
    int zhuliu()
    {
        int tot=0,cnt;
        while(1)
        {
            cnt=0;
            for(int i=1;i<=n;++i) ine[i]=inf,id[i]=vis[i]=0;
            for(int i=1;i<=m;++i)
            {
                int x=e[i].x,y=e[i].y,v=e[i].v;
                if(x!=y&&v<ine[y]) ine[y]=v,pre[y]=x;
            }
            for(int i=1;i<=n;++i)
                if(i!=root&&ine[i]==inf)
                    return -1;
            for(int i=1;i<=n;++i)
            {
                if(i==root) continue;
                tot+=ine[i];
                int y=i;
                while(vis[y]!=i&&!id[y]&&y!=root)
                {
                    vis[y]=i;
                    y=pre[y];
                }
                if(!id[y]&&y!=root)
                {
                    id[y]=++cnt;
                    for(int x=pre[y];x!=y;x=pre[x]) id[x]=cnt;
                }
            }
            if(!cnt) break;
            for(int i=1;i<=n;++i)
                if(!id[i])
                    id[i]=++cnt;
            for(int i=1;i<=m;++i)
            {
                int x=e[i].x,y=e[i].y;
                e[i].x=id[x],e[i].y=id[y];
                if(id[x]!=id[y]) e[i].v-=ine[y];
            }
            root=id[root];
            n=cnt;
        }
        return tot;
    }
    bool check(int x)
    {
    	root=1,n=p,m=0;
        for(int i=1;i<=q;++i)
            if(ed[i].b>=x)
                e[++m]=ed[i];
        int get=zhuliu();
        return get!=-1&&get<=c;
    }
    int main()
    {
        read(t);
        while(t--)
        {
            read(p),read(q),read(c);
            for(int i=1;i<=q;++i)
            {
                read(ed[i].x),read(ed[i].y),read(ed[i].b),read(ed[i].v);
                ed[i].x++,ed[i].y++;
            }
            l=0,r=maxc,ans=-1;
            while(l<=r)
            {
                int mid=(l+r)>>1;
                if(check(mid)) ans=mid,l=mid+1;
                else r=mid-1;
            }
            if(ans==-1) puts("streaming not possible.");
            else printf("%d kbps
    ",ans);
        }
    	return 0;
    }
    
    
  • 相关阅读:
    LeetCode-434-字符串中的单词数
    LeetCode-415-字符串相加
    字符串
    序列
    元组
    列表
    repr()与str的区别
    输出函数print()
    输入函数input()
    MySQL中快速复制数据表方法汇总
  • 原文地址:https://www.cnblogs.com/lhm-/p/12229854.html
Copyright © 2020-2023  润新知