zoukankan      html  css  js  c++  java
  • zoj

    Kawa Exam

    题解:先scc把图变成树, 然后对于这若干棵树在进行dsu的操作。

    dsu就是先找到最大的子树放在一边,然后先处理小的子树,最后处理大的子树。无限递归。

    重要的一点就是 是否重新添加每个点的值,每次处理完小的子树之后会清空影响,然后处理完最大的子树之后就不再清空影响,这样减少复杂度。 

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    #define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout);
    #define LL long long
    #define ULL unsigned LL
    #define fi first
    #define se second
    #define pb push_back
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define lch(x) tr[x].son[0]
    #define rch(x) tr[x].son[1]
    #define max3(a,b,c) max(a,max(b,c))
    #define min3(a,b,c) min(a,min(b,c))
    typedef pair<int,int> pll;
    const int inf = 0x3f3f3f3f;
    const LL INF = 0x3f3f3f3f3f3f3f3f;
    const LL mod =  (int)1e9+7;
    const int N = 2e5 + 100;
    int head[N], to[N<<1], nt[N<<1], tot = 0;
    void add(int u, int v){
        to[tot] = v;
        nt[tot] = head[u];
        head[u] = tot++;
    }
    int belong[N], dfn[N], low[N], now_time, scc_cnt;
    int now = 0, st[N], ed[N];
    vector<int> vc[N];
    vector<pll> e[N];
    stack<int> s;
    void dfs(int u, int id){
        dfn[u] = low[u] = ++now_time;
        s.push(u);
        for(int i = head[u]; ~i; i = nt[i]){
            if(i == (id^1)) continue;
            if(!dfn[to[i]]) dfs(to[i], i);
            if(!belong[to[i]]) low[u] = min(low[u], low[to[i]]);
        }
        if(dfn[u] == low[u]){
            ++scc_cnt;
            int now;
            while(1){
                now = s.top(); s.pop();
                belong[now] = scc_cnt;
                vc[scc_cnt].pb(now);
                if(now == u) break;
            }
        }
    }
    void scc(int n){
        for(int i = 1; i <= scc_cnt; ++i) {
            vc[i].clear();
            e[i].clear();
            st[i] = ed[i] = 0;
    
        } now = 0;
        for(int i = 1; i <= n; ++i) dfn[i] = low[i] = belong[i] = 0;
        while(!s.empty()) s.pop();
        now_time = scc_cnt = 0;
        for(int i = 1; i <= n; ++i)
            if(!belong[i]) dfs(i,-1);
         for(int i = 0, u, v; i <= tot; i += 2){
            u = to[i], v = to[i+1];
            u = belong[u], v = belong[v];
            if(u != v) e[u].pb(pll(v,i/2+1)), e[v].pb(pll(u,i/2+1));
        }
    }
    int vis[N], col[N], col2[N], cnt[N], cnt2[N], mx1, mx2;
    int sz[N], p[N];
    int a[N];
    void Add1(int u){
        for(int i = 0, x; i < vc[u].size(); ++i){
            x = vc[u][i];
            cnt[col[a[x]]]--;
            ++col[a[x]];
            cnt[col[a[x]]]++;
            if(mx1 < col[a[x]]) mx1 = col[a[x]];
        }
    }
    void Add2(int u){
        for(int i = 0, x; i < vc[u].size(); ++i){
            x = vc[u][i];
            cnt2[col2[a[x]]]--;
            ++col2[a[x]];
            cnt2[col2[a[x]]]++;
            if(mx2 < col2[a[x]]) mx2 = col2[a[x]];
        }
    }
    void Sub1(int u){
        for(int i = 0, x; i < vc[u].size(); ++i){
            x = vc[u][i];
            --cnt[col[a[x]]];
            --col[a[x]];
            ++cnt[col[a[x]]];
            if(cnt[mx1] == 0) --mx1;
        }
    }
    void Sub2(int u){
        for(int i = 0, x; i < vc[u].size(); ++i){
            x = vc[u][i];
            --cnt2[col2[a[x]]];
            --col2[a[x]];
            ++cnt2[col2[a[x]]];
            if(cnt2[mx2] == 0) --mx2;
        }
    }
    void ddfs(int o, int u){
        //cout << o << ' ' << u << endl;
        ++now;
        Add1(u);
        p[now] = u;
        st[u] = now;
        sz[u] = vc[u].size();
        for(int i = 0, v; i < e[u].size(); ++i){
            v = e[u][i].fi;
            if(v == o) continue;
            ddfs(u, v);
            sz[u] += sz[v];
        }
        ed[u] = now;
    }
    void Clear(int o, int u){
        Sub1(u);
       for(int i = 0; i < e[u].size(); ++i){
            int v = e[u][i].fi;
            if(v == o) continue;
            Clear(u, v);
        }
    }
    int ttttmp;
    int val[N];
    void dsu(int o, int u, int op, int id){
        int bigson = -1, mx = -1, iid;
        for(int i = 0, v; i < e[u].size(); ++i){
            v = e[u][i].fi;
            if(v == o) continue;
            if(mx < sz[v]) {
                mx = sz[v];
                bigson = v;
                iid = e[u][i].se;
            }
        }
        for(int i = 0, v; i < e[u].size(); ++i){
            v = e[u][i].fi;
            if(v == o || v == bigson) continue;
            dsu(u, v, 0, e[u][i].se);
        }
        if(bigson != -1)
            dsu(u, bigson, 1, iid);
        for(int i = 0, v; i < e[u].size(); ++i){
            v = e[u][i].fi;
            if(v != o && v != bigson)   {
                for(int i = st[v]; i <= ed[v]; i++){
                    Sub1(p[i]);
                    Add2(p[i]);
                }
            }
        }
        Sub1(u);
        Add2(u);
        val[id] = mx1+mx2-ttttmp;
        if(op == 0){
            for(int i = st[u]; i <= ed[u]; i++){
                Sub2(p[i]);
                Add1(p[i]);
            }
        }
    }
    void init(){
        memset(head, -1, sizeof(head));
        tot = 0;
    }
    int main(){
        int T, n, m;
        scanf("%d", &T);
    
        while(T--){
            init();
            scanf("%d%d", &n, &m);
            for(int i = 1; i <= n; ++i) scanf("%d", &a[i]);
            for(int i = 1, u, v; i <= m; ++i){
                scanf("%d%d", &u, &v);
                add(u,v); add(v,u);
            }
            scc(n);
            int ans = 0;
            for(int i = 1; i <= scc_cnt; ++i){
                if(st[i]) continue;
                mx1 = mx2 = 0;
                ddfs(0,i);
                ttttmp = mx1;
                ans += mx1;
                dsu(0,i,0,0);
                Clear(0,i);
            }
    //        cout << ans << endl;
            for(int i = 1; i <= m; i++){
                printf("%d%c", ans+val[i]," 
    "[i==m]);
                val[i] = 0;
            }
        }
        return 0;
    }
    /*
    3
    7 5
    1 2 1 2 1 2 1
    1 2
    1 3
    2 4
    5 6
    5 7
    3 3
    1 2 3
    1 2
    1 3
    2 3
    7 5
    1 2 1 2 1 2 1
    1 2
    1 3
    2 4
    5 6
    5 7
    */
    View Code
  • 相关阅读:
    Markdown示例
    初识Markdown
    Ubuntu源整理
    Vi编辑器入门
    Ubuntu,Linux入门系统
    [其他]volatile 关键字
    Qt5:随窗口大小变化背景图片自动缩放的实现
    Qt5:不规则按钮的实现---通过贴图实现
    windows编程:创建DLL
    [转]Firefox拦截12306订票网站的解决办法
  • 原文地址:https://www.cnblogs.com/MingSD/p/9942017.html
Copyright © 2011-2022 走看看