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

题目大意:有一张n个顶点,m条边的有向图,根节点为0。每条边有两个权值,一个是费用c,一个是长度b。问在总费用不超过cost的情况下选出若干条边,使得n个点连通时的边的最短长度的最大值是多少。

题目分析:如果已知这个最短距离的最大值d,则问题就变成了:用长度不小于d的边能否构成一个总权值不大于cost的最小树形图。因此,二分枚举d,用朱-刘 算法判断即可。

 

代码如下:

# include<iostream>
# include<cstdio>
# include<vector>
# include<cstring>
# include<algorithm>
using namespace std;
# define REP(i,s,n) for(int i=s;i<n;++i)
# define LL long long
# define CL(a,b) memset(a,b,sizeof(a))

const int INF=1<<30;
struct Edge
{
    int fr,to,w,d;
};
Edge e1[10005],e[10005];
int n,m,cost,vis[65],ID[65],pre[65],in[65];

int judge(int root,int nv,int ne)
{
    int res=0;
    while(1){
        REP(i,0,nv) in[i]=INF;
        REP(i,0,ne) if(e[i].fr!=e[i].to&&in[e[i].to]>e[i].w){
            in[e[i].to]=e[i].w;
            pre[e[i].to]=e[i].fr;
        }
        in[root]=0;
        REP(i,0,nv) if(in[i]==INF) return -1;
        int nodeCnt=0;
        CL(ID,-1);
        CL(vis,-1);
        REP(i,0,nv){
            res+=in[i];
            int v=i;
            while(vis[v]!=i&&ID[v]==-1&&v!=root){
                vis[v]=i;
                v=pre[v];
            }
            if(v!=root&&ID[v]==-1){
                for(int u=pre[v];u!=v;u=pre[u])
                    ID[u]=nodeCnt;
                ID[v]=nodeCnt++;
            }
        }
        if(nodeCnt==0) break;
        REP(i,0,nv) if(ID[i]==-1) ID[i]=nodeCnt++;
        REP(i,0,ne){
            int v=e[i].to;
            e[i].fr=ID[e[i].fr];
            e[i].to=ID[e[i].to];
            if(e[i].fr!=e[i].to)
                e[i].w-=in[v];
        }
        nv=nodeCnt;
        root=ID[root];
    }
    return res;
}

int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d%d",&n,&m,&cost);
        int l=0,r=0;
        REP(i,0,m){
            scanf("%d%d%d%d",&e1[i].fr,&e1[i].to,&e1[i].d,&e1[i].w);
            r=max(r,e1[i].d);
        }
        int ans=-1;
        while(l<r){
            int mid=l+(r-l+1)/2,cnt=0;
            REP(i,0,m) if(e1[i].d>=mid) e[cnt++]=e1[i];
            int x=judge(0,n,cnt);
            if(x>0&&x<=cost){
                ans=l=mid;
            }else
                r=mid-1;
        }
        if(ans<0)
            printf("streaming not possible.\n");
        else
            printf("%d kbps\n",ans);
    }
    return 0;
}

  

posted @ 2015-10-27 22:18  20143605  阅读(350)  评论(0编辑  收藏  举报