「BalkanOI 2018 Day1」Minmaxtree

「BalkanOI 2018 Day1」Minmaxtree

Each point has a maximum and minimum weight limit.

Then each weight limit value must be taken to.

Each point can obviously take him directly to the maximum or minimum weight.

It is contemplated that each point matching a weight.

Is not it a bipartite graph. . .

Each point is connected to the minimum and maximum weight and run Dinic, output scheme, of course, this problem can be ran Hungary.

The next requirement is to limit the weight of each value point: LCT may be directly labeled chain, down or offline, after sorting, were added, with a set of skip check point and has visited.

#include<bits/stdc++.h>
#define rep(q,a,b) for(int q=a,q##_end_=b;q<=q##_end_;++q)
#define dep(q,a,b) for(int q=a,q##_end_=b;q>=q##_end_;--q)
#define mem(a,b) memset(a,b,sizeof a )
#define debug(a) cerr<<#a<<' '<<a<<"___"<<endl
using namespace std;
void in(int &r){
    static char c;
    r=0;
    while(c=getchar(),!isdigit(c));
    do r=(r<<1)+(r<<3)+(c^48);
    while(c=getchar(),isdigit(c));
}
const int mn=70010;
int head[mn<<1],to[mn<<3],ne[mn<<3],cnt1,W[mn<<3],n;
#define link1(a,b) link_edge1(a,b),link_edge1(b,a)
#define link_edge1(a,b) to[++cnt1]=b,ne[cnt1]=head[a],head[a]=cnt1
#define travel(x) for(int q(head[x]);q;q=ne[q])
struct edge{
    int x,y;
}e[mn];
void link(int x,int y);
int cnt;
void pre_dfs(int f,int x){
    travel(x)if(to[q]!=f)e[++cnt]={x,to[q]},link(to[q],cnt+n),link(cnt+n,x),pre_dfs(x,to[q]);
}
int son[mn<<1][2],fa[mn<<1];
bool mark[mn<<1];
int Min[mn<<1],Max[mn<<1];
int minv[mn<<1],maxv[mn<<1];
bool noroot(int x){
    return x==son[fa[x]][0]||x==son[fa[x]][1];
}
void rotate(int x){
    int y=fa[x],z=fa[y],d=x==son[y][1];
    if(noroot(y))son[z][y==son[z][1]]=x;
    son[y][d]=son[x][!d];
    fa[son[x][!d]]=y;
    son[x][!d]=y;
    fa[x]=z,fa[y]=x;
}
int sta[mn<<1],tp;
void res(int x){
    if(!x)return;
    swap(son[x][0],son[x][1]);
    mark[x]^=1;
}
void min_mark(int x,int v){
    if(!x)return;
    if(!minv[x])minv[x]=v;
    else minv[x]=max(v,minv[x]);
    if(!Min[x])Min[x]=v;
    else Min[x]=max(Min[x],v);
}
void max_mark(int x,int v){
    if(!x)return;
    if(!maxv[x])maxv[x]=v;
    else maxv[x]=min(v,maxv[x]);
    if(!Max[x])Max[x]=v;
    else Max[x]=min(Max[x],v);
}
void push_down(int x){
    int ls=son[x][0],rs=son[x][1];
    if(mark[x]){
        res(ls);
        res(rs);
        mark[x]=0;
    }
    if(Min[x]){
        min_mark(ls,Min[x]);
        min_mark(rs,Min[x]);
        Min[x]=0;
    }
    if(Max[x]){
        max_mark(ls,Max[x]);
        max_mark(rs,Max[x]);
        Max[x]=0;
    }
}
void splay(int x){
    tp=0;
    int now=x;
    while(noroot(now))sta[++tp]=now,now=fa[now];
    sta[++tp]=now;
    dep(q,tp,1)push_down(sta[q]);
    while(noroot(x)){
        int y=fa[x];
        if(noroot(y))(x==son[y][1])==(y==son[fa[y]][1])?rotate(y):rotate(x);
        rotate(x);
    }
}
void access(int x){
    for(int y=0;x;y=x,x=fa[x])splay(x),son[x][1]=y;
}
void makeroot(int x){
    access(x),splay(x),res(x);
}
void split(int x,int y){
    makeroot(x);
    access(y),splay(y);
}
void link(int x,int y){
    fa[x]=y;
}
int px[mn],ll[mn],rr[mn],hd=0;
void solve(){
    int a,b,v,Q;
    in(Q);
    char c;
    while(Q--){
        while(c=getchar(),!isalpha(c));
        in(a),in(b),in(v);
        px[++hd]=v;
        split(a,b);
        if(c=='M')max_mark(b,v);
        else min_mark(b,v);
    }
}
void get_min_max(){ 
    sort(px+1,px+hd+1);
    rep(q,1,n-1){
        splay(n+q);
        ll[q]=minv[n+q],rr[q]=maxv[n+q];
    }
}
void clear_edge(){
    rep(q,1,n)head[q]=0;
    cnt1=1;
}
void link_edge(int x,int y,int z){
    to[++cnt1]=y,ne[cnt1]=head[x],head[x]=cnt1;
    W[cnt1]=z;
}
void link_w(int x,int y,int z){
    link_edge(x,y,z);
    link_edge(y,x,0);
}
int S,T,tot_node;
void build_graph(){
    S=n-1+hd+1;
    T=S+1;
    tot_node=T;
    rep(q,1,n-1)link_w(S,q,1);
    rep(q,1,hd)link_w(q+n-1,T,1);
    rep(q,1,n-1){
        if(ll[q])ll[q]=lower_bound(px+1,px+hd+1,ll[q])-px,link_w(q,ll[q]+n-1,1);
        if(rr[q])rr[q]=lower_bound(px+1,px+hd+1,rr[q])-px,link_w(q,rr[q]+n-1,1);
    }
}
int depth[mn<<1],cur[mn<<1],que[mn<<1];
bool bfs(){
    rep(q,1,tot_node)depth[q]=-1;
    int l=0,r=0;
    que[++r]=S;
    depth[S]=1;
    while(l<r){
        int now=que[++l];
        travel(now)if(depth[to[q]]==-1&&W[q]){
            depth[to[q]]=depth[now]+1;
            que[++r]=to[q];
            if(to[q]==T)return 1;
        }
    }
    return 0;
}
int dfs(int x,int flow){
    if(!flow||x==T)return flow;
    int used=0;
    for(int &q=cur[x];q;q=ne[q])if(depth[to[q]]==depth[x]+1){
        int fl=dfs(to[q],min(flow-used,W[q]));
        W[q]-=fl;
        W[q^1]+=fl;
        used+=fl;
        if(used==flow)return used;
    }
    if(!used)depth[x]=-1;
    return used;
}
void bipartite_match(){
    while(bfs()){
        rep(q,1,tot_node)cur[q]=head[q];
        dfs(S,1e9);
    }
}
bool mk[mn];
const int Rand_lim=1e9;
void out(){
    rep(w,1,n-1){
        bool ok=0;
        travel(w)if(to[q]!=S&&to[q]>=n&&W[q]==0){
            printf("%d %d %d\n",e[w].x,e[w].y,px[to[q]-(n-1)]);
            mk[to[q]-(n-1)]=1;
            ok=1;
        }
        if(!ok)printf("%d %d %d\n",e[w].x,e[w].y,rr[w]?px[rr[w]]:px[ll[w]]);
    }
}
int main(){
    freopen("minmaxtree.in","r",stdin);
    freopen("minmaxtree.out","w",stdout);
    srand(time(NULL));
    int a,b;
    in(n);
    rep(q,2,n)in(a),in(b),link1(a,b);
    pre_dfs(0,1);
    
    solve();
    
    get_min_max();
    
    clear_edge();
    
    build_graph();
    
    bipartite_match();
    
    out();
    return 0;
}

Guess you like

Origin www.cnblogs.com/klauralee/p/11305097.html