zoukankan      html  css  js  c++  java
  • 【HDU 4547】 CD操作

    【题目链接】

              点击打开链接

    【算法】

              分四种情况讨论 :

              1. 当前目录和目标目录是同一目录,不需要变换,答案为0

              2. 当前目录是目标目录的祖先,答案为当前目录的深度 - 目标目录的深度

              3. 当前目录是目标目录的孩子,答案为1

              4. 当前目录和目标目录有最近公共祖先,答案为当前目录的深度 - 最近公共祖先的深度 + 1

              那么,算法就很明确了,先做一遍离线tarjan,求出询问点对的最近公共祖先,然后,进行上述的分类讨论

    【代码】

              由于目录名称是字符串,笔者用stl库里的map将这些目录重新编号

              

    #include<bits/stdc++.h>
    using namespace std;
    #define MAXN 100010
    #define MAXL 45
    
    struct Edge
    {
            int to,nxt;
    } e[MAXN];
    
    int i,T,tot,id,n,m,root;
    int head[MAXN],dep[MAXN],f[MAXN],lca[MAXN],fa[MAXN];
    string a,b;
    string x[MAXN],y[MAXN];
    bool visited[MAXN];
    map<string,int> mp;
    vector< pair<int,int> > query[MAXN];
    
    inline void add(int u,int v)
    {
            tot++;
            e[tot] = (Edge){v,head[u]};
            head[u] = tot;
    }
    inline void init(int u)
    {
            int i,v;
            for (i = head[u]; i; i = e[i].nxt)
            {
                    v = e[i].to;
                    dep[v] = dep[u] + 1;
                    init(v);
            }        
    }
    inline int find(int x)
    {
            if (f[x] == x) return x;
            return f[x] = find(f[x]);
    }
    inline void tarjan(int u)
    {
            int i,v,pos;
            visited[u] = true;
            f[u] = u;
            for (i = 0; i < query[u].size(); i++)
            {
                  v = query[u][i].first;
                  pos = query[u][i].second;
                  if (visited[v]) lca[pos] = find(v);
            }
            for (i = head[u]; i; i = e[i].nxt)
            {
                    v = e[i].to;
                    tarjan(v);
                    f[v] = u;
            }
    }
    
    int main() 
    {
            
            ios :: sync_with_stdio(0);
            cin.tie(0);
            
            cin >> T;
            while (T--)
            {
                    cin >> n >> m;
                    tot = id = 0;
                    mp.clear();
                    for (i = 1; i <= n; i++)
                    {
                            head[i] = 0;
                            fa[i] = 0;
                            visited[i] = false;
                            query[i].clear();
                    }
                    for (i = 1; i < n; i++) 
                    {
                            cin >> a >> b;
                            if (!mp[a]) mp[a] = ++id;
                            if (!mp[b]) mp[b] = ++id;    
                            add(mp[b],mp[a]);
                            fa[mp[a]] = mp[b];
                    }    
                    for (i = 1; i <= n; i++) 
                    {
                            if (!fa[i])
                                    root = i;
                    }
                    dep[root] = 0;
                    init(root);
                    for (i = 1; i <= m; i++) 
                    {
                            cin >> x[i] >> y[i];
                            query[mp[x[i]]].push_back(make_pair(mp[y[i]],i));
                            query[mp[y[i]]].push_back(make_pair(mp[x[i]],i));
                    }
                    tarjan(root);
                    for (i = 1; i <= m; i++) 
                    {
                            if (x[i] == y[i]) printf("%d
    ",0);
                            else if (lca[i] == mp[x[i]]) printf("%d
    ",1);
                            else if (lca[i] == mp[y[i]]) printf("%d
    ",dep[mp[x[i]]]-dep[mp[y[i]]]);
                            else printf("%d
    ",dep[mp[x[i]]]-dep[lca[i]]+1);
                    }
            }
            
            return 0;
        
    }
  • 相关阅读:
    属于程序员的算法
    知乎:全栈工程师讨论
    盘点2015年前20款表现出色的免费开源软件
    qt学习之路
    ubuntu联网经常掉线的解决方法
    备份书签
    linux 命令行测试网速
    linux中判断ssh是否启动
    php heredoc 与 nowdoc
    php 双向队列类
  • 原文地址:https://www.cnblogs.com/evenbao/p/9196306.html
Copyright © 2011-2022 走看看