uva 12587 二分枚举

思路:维护一个森林,二分枚举最小的最大值。

#include<set>

#include<map>

#include<cmath>

#include<queue>

#include<cstdio>

#include<vector>

#include<string>

#include<cstdlib>

#include<cstring>

#include<iostream>

#include<algorithm>

#define pb push_back

#define mp make_pair

#define Maxn 20010

#define Maxm 40010

#define LL long long

#define Abs(x) ((x)>0?(x):(-x))

#define lson(x) (x<<1)

#define rson(x) (x<<1|1)

#define inf 1e15

#define lowbit(x) (x&(-x))

#define clr(x,y) memset(x,y,sizeof(x))

#define Mod 1000000007

using namespace std;

int head[Maxn],vi[Maxn],dfn[Maxn],low[Maxn],num[Maxn],is[Maxn],Stack[Maxn],top,e,lab;

int n,m;

LL val[Maxn],need[Maxn],cnt;

struct Edge{

    int u,v,next,f;

    LL val;

}edge[Maxm];

void init()

{

    clr(head,-1);

    clr(vi,0);

    clr(is,0);

    clr(need,0);

    clr(dfn,0);

    clr(low,0);

    clr(num,0);

    e=lab=cnt=0;

}

void add(int u,int v,LL val)

{

    //cout<<u<<" "<<v<<endl;

    edge[e].u=u,edge[e].v=v,edge[e].val=val,edge[e].f=0,edge[e].next=head[u],head[u]=e++;

}

void Tarjan(int u)

{

    int i,v,cc;

    ++cnt;

    vi[u]=1;

    dfn[u]=low[u]=++lab;

    Stack[++top]=u;

    for(i=head[u];i!=-1;i=edge[i].next){

        v=edge[i].v;

        if(edge[i].f) continue;

        edge[i].f=edge[i^1].f=1;

        if(!dfn[v]){

            cc=cnt;

            Tarjan(v);

            if(low[v]>dfn[u]){

                is[u]=1;

                num[v]=cnt-cc;

            }

            low[u]=min(low[u],low[v]);

        }

        else low[u]=min(low[u],dfn[v]);

    }

}

bool dfs(int u,LL nal)

{

    int i,v;

    need[u]=val[u];

    vi[u]=1;

    for(i=head[u];i!=-1;i=edge[i].next){

        v=edge[i].v;

        if(vi[v]) continue;

        if(!dfs(v,nal))

            return false;

        if(is[u]){

            if(num[v]*(cnt-num[v])*edge[i].val+need[v]>nal)

                need[u]+=num[v]*(cnt-num[v])*edge[i].val;

        }

        if(need[u]>nal)

            return false;

    }

    return true;

}

bool OK(LL x,int p)

{

    int i,j;

    for(i=0;i<=top;i++) vi[Stack[i]]=0;

    for(i=0;i<=top;i++) if(val[Stack[i]]>x){

        return false;

    }

    if(!dfs(p,x))

        return false;

    return true;

}

void solve()

{

    int i,j;

    LL ans=0;

    for(i=1;i<=n;i++) if(!dfn[i]){

        Tarjan(i);

        LL l,r,mid;

        l=0,r=inf;

        while(l<r){

            mid=(l+r)>>1;

            if(OK(mid,i))

                r=mid;

            else

                l=mid+1;

        }

        ans=max(l,ans);

        cnt=0;

        top=0;

    }

    printf("%lld\n",ans);

    return ;

}

int main()

{

    int i,j,u,v,t,Ca=0;

    LL cc;

    scanf("%d",&t);

    while(t--){

        init();

        scanf("%d%d",&n,&m);

        for(i=1;i<=n;i++)

            scanf("%lld",val+i);

        for(i=1;i<=m;i++){

            scanf("%d%d%lld",&u,&v,&cc);

            add(u,v,cc);

            add(v,u,cc);

        }

        printf("Case %d: ",++Ca);

        solve();

    }

    return 0;

}

 

你可能感兴趣的:(uva)