agc041 **Balancing Network** 题解

agc041 Balancing Network 题解

很有趣的构造题:

Case 1

如何使流汇聚到一条边上?

可以倒推。

假设最后都汇聚到\(x\)

维护一个集合\(S\),表示可以有流量的边,初始\(S=\{x\}\)

从后往前遇到边\(x_i,y_i\)。如果\(x_i,y_i\)之一在\(S\)中,则加入\(x_i,y_i\)

最后判断一下\(S\)是否是全集即可,复杂度\(O(nm)\)

优化:

构造一个\(n\)个点的图。

可以将\(x_i,y_i\)看作在\(x_i,y_i\)中间连一个权值为\(i\)的边。

一个点\(y\)最终能在集合中当且仅当存在一个路径\(x,s_1,s_2...s_n,y\),满足边\(s_i,s_{i+1}\)的权值\(\leq s_{i+1},s_{i}\)

为了避免重边,可以对于\(x_i,y_i\)新建两个点,有颜色\(x_i,y_i\)

问题就是能否从一个点出发到达所有颜色,\(bitset\)优化即可。

时间复杂度\(O(\frac{nm}{w})\)

Case 2

解法1:

我的想法是和\(1\)差不多做。

从后往前倒推,维护一个二元组\((x,y)\)

表示最终必须保证\(x,y\)有流量。

可以\(dp\)解决,时间复杂度\(O(mn)\)

但是注意到若\(n\geq 500\),则一定存在一个\(x,y\)满足\(x,y\)中没有边,可以很容易构造。

所以时间和空间复杂度为\(O(m\sqrt m)\)

解法2:

题解做法:

从后往前。

注意到若\(n\geq 3\),则一定有解。

对于每一条边维护一个数组\(B_i\)表示从\(i\)出发最终会在哪里结束?

\(B_i\)最终全相等就不行。

对于一个\(x,y\),本质上是令\(B_x\Leftarrow B_y\)或者\(B_y\Leftarrow B_x\)

可以发现\(n\geq 3\)是不存在只有\(B_x,B_y\)两种数,且个数都为\(1\)

直接构造的复杂度为\(O(N)\)

#include<bits/stdc++.h>
#define rb(a,b,c) for(int a=b;a<=c;++a)
#define rl(a,b,c) for(int a=b;a>=c;--a)
#define rep(a,b) for(int a=0;a<b;++a)
#define LL long long
#define PB push_back
#define POB pop_back
#define II(a,b) make_pair(a,b)
#define FIR first
#define SEC second
#define SRAND mt19937 rng(chrono::steady_clock::now().time_since_epoch().count())
#define random(a) rng()%a
#define ALL(a) a.begin(),a.end()
#define check_min(a,b) a=min(a,b)
#define check_max(a,b) a=max(a,b)
using namespace std;
const int INF=0x3f3f3f3f;
typedef pair<int,int> mp;
const int MAXN=1e5+1;
int n,m,t;
int x[MAXN],y[MAXN];
int pre[MAXN];
bool ok[MAXN];
bitset<50000> vis[100001];
void construct1(){
    rb(i,1,m){
        vis[i].set(x[i]);
        vis[i].set(y[i]);
        if(pre[x[i]]) vis[i]|=vis[pre[x[i]]];
        if(pre[y[i]]) vis[i]|=vis[pre[y[i]]];
        pre[x[i]]=pre[y[i]]=i;
    }
    rep(i,n){
        if(vis[pre[i]].count()==n){
            ok[i]=1;
            string answer;
            rl(j,m,1){
                if(ok[x[j]]||ok[y[j]]){
                    if(ok[x[j]]) answer.PB('^');
                    else answer.PB('v');
                    ok[x[j]]=ok[y[j]]=1;
                }
                else{
                    answer.PB('v');
                }
            }
            reverse(ALL(answer));
            cout<<answer<<endl;
            return ;
        }
    }
    cout<<-1<<endl;
    return ;
}
char ans[100000+20];
pair<short,short> dp[100000+20][2][500];
int pr[100000+20][2][500];
mp gt(int i,int a,int b){
	if(b==x[i]||b==y[i]) swap(a,b);
    if(a==x[i]) return II(0,b);
    return II(1,b);
}
void recover(int i,short a,short b){
    if(i==0) return ;
    auto A=dp[i][gt(i,a,b).FIR][gt(i,a,b).SEC];
    auto B=pr[i][gt(i,a,b).FIR][gt(i,a,b).SEC];
    if(A==II(a,b)){
        if(b==x[i]||b==y[i]) swap(a,b);
        if(a==x[i]){
            ans[i]='^';
        }
    }
    else{
        tie(a,b)=A;
        if(b==x[i]||b==y[i]) swap(a,b);
        if(a==y[i]){
            ans[i]='^';
        }
    }
    recover(B,A.FIR,A.SEC);
}
void construct2(){
  	if(n>=500){
        map<mp,int> gg;
        rb(i,1,m) gg[II(x[i],y[i])]=gg[II(y[i],x[i])]=1;
        rep(i,n){
            rep(j,i){
                if(gg[II(i,j)]==0){
                    rb(k,1,m){
                        if(x[k]==i||x[k]==j){
                            cout<<'^';
                        }
                        else{
                            cout<<"v";
                        }
                    }
                    cout<<endl;
                    return ;
                }
            }
        }
     	return;
    }
    rb(i,0,m) rep(j,2) rep(k,500) dp[i][j][k]=II(-1,-1);
    rb(i,1,m) ans[i]='v';
    rb(i,1,m){
        rep(k,n){
            if(k!=x[i]&&k!=y[i]){
                int a,b,j;
                a=min(k,x[i]);
                b=max(k,x[i]);
                int c,d;
                c=min(k,y[i]);
                d=max(k,y[i]);
                j=max(pre[a],pre[b]);
                if(j==0||dp[j][gt(j,a,b).FIR][gt(j,a,b).SEC].FIR!=-1){
                    dp[i][gt(i,c,d).FIR][gt(i,c,d).SEC]=II(a,b);
                    dp[i][gt(i,a,b).FIR][gt(i,a,b).SEC]=II(a,b);
                    pr[i][gt(i,c,d).FIR][gt(i,c,d).SEC]=j;
                    pr[i][gt(i,a,b).FIR][gt(i,a,b).SEC]=j;
                    continue;
                }
                j=max(pre[c],pre[d]);
                if(j==0||dp[j][gt(j,c,d).FIR][gt(j,c,d).SEC].FIR!=-1){
                    dp[i][gt(i,c,d).FIR][gt(i,c,d).SEC]=II(c,d);
                    dp[i][gt(i,a,b).FIR][gt(i,a,b).SEC]=II(c,d);
                    pr[i][gt(i,c,d).FIR][gt(i,c,d).SEC]=j;
                    pr[i][gt(i,a,b).FIR][gt(i,a,b).SEC]=j;
//                    continue;
                }
            }
        }
//         cout<<i<<" "<<dp[i].size()<<endl;
        pre[x[i]]=pre[y[i]]=i;
    }
    rep(i,n) rep(j,i) if(max(pre[i],pre[j])==0||dp[max(pre[i],pre[j])][gt(max(pre[i],pre[j]),j,i).FIR][gt(max(pre[i],pre[j]),j,i).SEC].FIR!=-1){
        recover(max(pre[i],pre[j]),j,i);
        rb(i,1,m) cout<<ans[i];
        cout<<endl;
        return ;
    }
    cout<<"-1\n";
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cin>>n>>m>>t;
    rb(i,1,m) cin>>x[i]>>y[i],x[i]--,y[i]--;
    if(t==1) construct1();
    else construct2();
    return 0;
}
posted @ 2021-12-07 23:01  WWW~~~  阅读(36)  评论(0编辑  收藏  举报