zoukankan      html  css  js  c++  java
  • 2019 Multi-University Training Contest 3 B 支配树

    题目传送门

    题意:给出衣服有向无环图(DAG),,定义出度为0的点为中心城市,每次询问给出两个点,求破坏任意一个城市,使得这两个点至少有一个点无法到达中心城市,求方案数。

    思路:首先建立反向图,将城市到若干个终点看成从若干个起点出发到某个城市,再用一个源点连接那些度为0    的点,即可看成从源点出发到某个城市。要炸掉一个点使得无法到达某个城市,那么需要炸掉的是从源点到该城市的必经点,考虑建立支配树,根据定义可知支配树到根的链上结点个数就是必经点的个数。两个城市的容斥减去 LCA 到根上这条链即可。由于保证是 DAG ,因此直接按拓扑序建树即可,建完树利用结点的 depth 来求点到根的链长,注意最后答案要减去一开始添加的源点。

      DAG支配树求法:先求拓扑序,按照拓扑序处理(建树)。对于一个点,所有能到达它的点在支配树中的lca,就是它支配树中的父亲。由于能到达他的点拓扑序必定比他本身小,所以肯定已经在建好的支配树上了,必定能求出lca。

      现在还不会非DAG的支配树,学习博客为  https://wenku.baidu.com/view/b06471d019e8b8f67d1cb91b.html

    #include<bits/stdc++.h>
    #define pb(a) push_back(a)
    #define clr(a) memset(a, 0, sizeof(a))
    using namespace std;
    const int maxn = 1e5 + 5;
    vector<int >ve[maxn],rve[maxn];
    int n,m,T;
    int deg[maxn],dep[maxn],id[maxn],tot;
    int f[maxn][20];
    int rt=n+1;
    void bfs(){
        rt=n+1;
        queue<int >q;
        for(int i=1;i<=n;i++){
            if(!deg[i]){
                q.push(i);
                ve[i].pb(rt);
                rve[rt].pb(i);
            }
        }
        while(!q.empty()){
            int u=q.front();
            q.pop();
            id[++tot]=u;
            int si=rve[u].size();
            for(int i=0;i<si;i++){
                int v=rve[u][i];
                if((--deg[v])==0){
                    q.push(v);
                }
            }
        }
    }
    int LCA(int x,int y){
        if(dep[x]>dep[y])swap(x,y);
        for(int i=19;i>=0;i--){
            if(dep[y]>dep[x]&&dep[x]<=dep[f[y][i]])y=f[y][i];
        }
        for(int i=19;i>=0;i--){
            if(f[x][i]!=f[y][i])x=f[x][i],y=f[y][i];
        }
        return x==y?x:f[x][0];
    }
    int main(){
        cin>>T;
        while(T--){
            cin>>n>>m;
            for(int i=1;i<=n+1;i++){
                ve[i].clear(),rve[i].clear();
                deg[i]=dep[i]=0;
            }
            tot=0;
            for(int i=1;i<=m;i++){
                int u,v;
                scanf("%d%d",&u,&v);
                ve[u].pb(v);
                rve[v].pb(u);
                deg[u]++;
            }
            bfs();
            dep[rt]=1;
            for(int i=1;i<=n;i++){
                int fa=-1;
                int u=id[i];
                int si=ve[u].size();
                for(int j=0;j<si;j++){
                    int v=ve[u][j];
                    fa=(fa==-1)?v:LCA(fa,v);
                }
                dep[u]=dep[fa]+1;
                f[u][0]=fa;
                for(int j=1;j<=19;j++){
                    f[u][j]=f[f[u][j-1]][j-1];
                }
            }
            int q,u,v;
            cin>>q;
            while(q--){
                scanf("%d%d",&u,&v);
                int lca=LCA(u,v);
                printf("%d
    ",dep[u]+dep[v]-dep[lca]-1);
            }
        }
    }
  • 相关阅读:
    当spfile文件中的参数修改错误,导致数据库无法启动问题
    oracle的shared server模式和dedicated server模式
    概述oracle的内存结构
    oracle进程简介
    TNS12516及ORA12516错误解决
    如何打补丁及升级
    关于sqlplus的简单概述
    修改参数之后数据库无法启动问题
    oracle的后台进程杀掉会有什么影响
    远程连接oracle数据库ORA12154错误
  • 原文地址:https://www.cnblogs.com/mountaink/p/11310928.html
Copyright © 2011-2022 走看看