zoukankan      html  css  js  c++  java
  • NOIP 模拟 $38; m c$

    题解 (by;zjvarphi)

    发现就是一棵树,但每条边都有多种不同的颜色,其实只需要保留随便三种颜色即可。

    直接点分治,将询问离线,分成一端为重心,和两端都不为重心的情况。

    每次只关心经过重心的询问,其他询问不管,具体实现就是点分治的套路,每次搜一棵子树,更新标记。

    动规有些小细节,尽量边权化点权,不容易出错,式子直接看官方题解。

    复杂度 (mathcal O m(3^3nlogn+3^4q))

    Code
    #include<bits/stdc++.h>
    #define Re register
    #define ri Re signed
    #define p(i) ++i
    namespace IO{
        char buf[1<<21],*p1=buf,*p2=buf;
        #define gc() p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?(-1):*p1++
        struct nanfeng_stream{
            template<typename T>inline nanfeng_stream &operator>>(T &x) {
                Re bool f=0;x=0;Re char ch=gc();
                while(!isdigit(ch)) f|=ch=='-',ch=gc();
                while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=gc();
                return x=f?-x:x,*this;
            }
        }cin;
    }
    using IO::cin;
    namespace nanfeng{
        #define node(x,y) (node){x,y}
        #define pb emplace_back
        #define fi first
        #define se second
        #define mk std::make_pair
        #define FI FILE *IN
        #define FO FILE *OUT
        template<typename T>inline T cmax(T x, T y) {return x>y?x:y;}
        template<typename T>inline T cmin(T x, T y) {return x>y?y:x;}
        static const int N=1e5+7;
        int first[N],dp[N][4][4],W[N][4],nm[N],tmp[4],G[N],siz[N],ans[N<<2],vis[N],dep,rt,pos,q,cnt,t=1,n,m;
        struct node{int v,i;}ask;
        std::vector<node> vc[N];
        struct edge{int v,nxt,w[4],nm;}e[N<<1];
        std::map<std::pair<int,int>,std::set<int> > mp;
        inline void add(int u,int v,int *w,int nm) {
            e[t].v=v,e[t].nm=nm;
            for (ri i(1);i<=nm;p(i)) e[t].w[i]=w[i];
            e[t].nxt=first[u],first[u]=t++;
            e[t].v=u,e[t].nm=nm;
            for (ri i(1);i<=nm;p(i)) e[t].w[i]=w[i];
            e[t].nxt=first[v],first[v]=t++;
        }
        void dfs_find(int S,int x,int fa) {
            siz[x]=1;
            int GS=0;
            for (ri i(first[x]),v;i;i=e[i].nxt) {
                if ((v=e[i].v)==fa||G[v]) continue;
                dfs_find(S,v,x);
                siz[x]+=siz[v];
                GS=cmax(GS,siz[v]);
            }
            GS=cmax(GS,S-siz[x]);
            if (GS<cnt) cnt=GS,pos=x;
        }
        void dfs_solve(int x,int fa) {
            siz[x]=1;
            for (ri i(first[x]),v;i;i=e[i].nxt) {
                if ((v=e[i].v)==fa||G[v]) continue;
                for (ri j(1);j<=e[i].nm;p(j)) W[v][j]=e[i].w[j];
                nm[v]=e[i].nm;
                for (ri l(1);l<=nm[rt];p(l))
                    for (ri j(1);j<=nm[v];p(j)) 
                        for (ri k(1);k<=nm[x];p(k)) 
                            if (W[x][k]==W[v][j]) dp[v][l][j]=cmax(dp[v][l][j],dp[x][l][k]);
                            else dp[v][l][j]=cmax(dp[v][l][j],dp[x][l][k]+1);
                dfs_solve(v,x);
                siz[x]+=siz[v];
            }
        }
        void dfs_query(int x,int fa) {
            for (auto nx:vc[x]) {
                if (!vis[nx.v]&&nx.v!=pos) continue;
                if (nx.v==pos) {
                    for (ri i(1);i<=nm[rt];p(i)) 
                        for (ri j(1);j<=nm[x];p(j))
                            ans[nx.i]=cmax(ans[nx.i],dp[x][i][j]);
                } else {
                    for (ri i(1);i<=nm[rt];p(i)) 
                        for (ri j(1);j<=nm[vis[nx.v]];p(j)) 
                            for (ri k(1);k<=nm[x];p(k))
                                for (ri l(1);l<=nm[nx.v];p(l)) {
                                    if (W[vis[nx.v]][j]==W[rt][i]) ans[nx.i]=cmax(ans[nx.i],dp[x][i][k]+dp[nx.v][j][l]-1);
                                    else ans[nx.i]=cmax(ans[nx.i],dp[x][i][k]+dp[nx.v][j][l]);
                                }
                }
            }
            for (ri i(first[x]),v;i;i=e[i].nxt) {
                if ((v=e[i].v)==fa||G[v]) continue;
                dfs_query(v,x);
            }
        }
        void dfs_mark(int x,int fa) {
            vis[x]=rt;
            for (ri i(first[x]),v;i;i=e[i].nxt) {
                if ((v=e[i].v)==fa||G[v]) continue;
                dfs_mark(v,x);
            }
        }
        void dfs_init(int x,int fa) {
            vis[x]=0;
            memset(dp[x],0,sizeof(dp[x]));
            for (ri i(first[x]),v;i;i=e[i].nxt) {
                if (G[v=e[i].v]||v==fa) continue;
                dfs_init(v,x);
            }
        }
        void solve(int S,int x) {
            dfs_find(cnt=S,x,0);
            dfs_init(pos,0);
            int np;
            G[np=pos]=1;
            for (ri i(first[np]),v;i;i=e[i].nxt) {
                if (G[v=e[i].v]) continue;
                for (ri j(1);j<=e[i].nm;p(j)) dp[v][j][j]=1,W[v][j]=e[i].w[j];
                nm[v]=e[i].nm;
                dfs_solve(rt=v,np);
                dfs_query(v,np);
                dfs_mark(v,np);
            }
            dfs_init(pos,0);
            for (ri i(first[np]),v;i;i=e[i].nxt) {
                if (G[v=e[i].v]) continue;
                solve(siz[v],v);
            }
        }
        inline int main() {
            //FI=freopen("nanfeng.in","r",stdin);
            //FO=freopen("nanfeng.out","w",stdout);
            cin >> n >> m;
            for (ri i(1),u,v,w;i<=m;p(i)) {
                cin >> u >> v >> w;
                if (u>v) std::swap(u,v);
                mp[mk(u,v)].insert(w);
            }
            for (auto x:mp) {
                ri ct=0;
                Re std::pair<int,int> tp=x.fi;
                Re std::set<int> tps=x.se;
                if (tps.size()>3) for (auto w:tps) {tmp[++ct]=w;if (ct==3) break;}
                else for (auto w:tps) tmp[++ct]=w;
                add(tp.fi,tp.se,tmp,ct);
            }
            cin >> q;
            for (ri i(1),u,v;i<=q;p(i)) cin >> u >> v,vc[u].pb(node(v,i)),vc[v].pb(node(u,i)); 
            solve(n,1);
            for (ri i(1);i<=q;p(i)) printf("%d
    ",ans[i]);
            return 0;
        }
    }
    int main() {return nanfeng::main();}
    
  • 相关阅读:
    vscode使用SSH Targets连接远程系统进行开发
    python2.7版本安装pip
    ubuntu系统安装最新版本nodejs
    win7安装yarn后执行报错
    Object合并,并使用默认值处理
    解决JSON.stringify序列化循环依赖对象报错
    docker环境下安装maven私服和gitlab
    单例模式的无锁实现
    【Java学习笔记】Java的垃圾回收机制
    Ubuntu下源码安装Python
  • 原文地址:https://www.cnblogs.com/nanfeng-blog/p/15139213.html
Copyright © 2011-2022 走看看