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;
}

 

posted @ 2013-09-30 21:09  fangguo  阅读(168)  评论(0编辑  收藏  举报