• 支配树


    原图-->dfs图-->支配树

    支配点:支配树中Y的祖先加上它自己 都是Y的支配点.去掉支配点使得在原图中源点无法到达Y(即必经点)

    最近支配点:支配树中Y最近的祖先

    半支配点:在dfs tree中可以通过非dfs tree中的边到达y的深度最小的节点x 为y的半支配点

    Lengauer-Tarjan算法 O(nlogn)

    利用并查集

    1.dfs构建搜索树 计算出dfn

    2.按时间戳从大到小的顺序算出每个节点的半支配点

    3.按照时间戳从小到大的顺序把半支配点≠支配点的节点进行修正

    HDU 4694

    /*Huyyt*/
    #include<bits/stdc++.h>
    #define mem(a,b) memset(a,b,sizeof(a))
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    const double eps = 1e-8;
    const int dir[8][2] = {{0, 1}, {1, 0}, {0, -1}, { -1, 0}, {1, 1}, {1, -1}, { -1, -1}, { -1, 1}};
    const int mod = 1e9 + 7, gakki = 5 + 2 + 1 + 19880611 + 1e9;
    const int MAXN = 5e5 + 5, MAXM = 2e5 + 5;
    const int MAXQ = 100010, INF = 1e9;
    /*int to[MAXM << 1], nxt[MAXM << 1], Head[MAXN], tot = 1;
    int TO[MAXM << 1], NXT[MAXM << 1], HEAD[MAXN], TOT = 1;
    ll cost[MAXM << 1];
    struct node
    {
            int u, v;
            ll c;
    } edge[MAXM];
    inline void addedge(int u, int v)
    {
            to[++tot] = v;
            nxt[tot] = Head[u];
            //cost[tot] = c;
            Head[u] = tot;
    }*/
    
    inline void read(int &v)
    {
            v = 0;
            char c = 0;
            int p = 1;
            while (c < '0' || c > '9')
            {
                    if (c == '-')
                    {
                            p = -1;
                    }
                    c = getchar();
            }
            while (c >= '0' && c <= '9')
            {
                    v = (v << 3) + (v << 1) + c - '0';
                    c = getchar();
            }
            v *= p;
    }
    int dfn[MAXN], idom[MAXN], sdom[MAXN];
    int son[MAXN], id[MAXN], fa[MAXN], f[MAXN];
    int ans[MAXN];
    int cnt;
    int n, m;
    vector<int> yuantu[MAXN], fantu[MAXN], zhipei[MAXN];
    int findfather(int x)
    {
            if (f[x] == x)
            {
                    return x;
            }
            int y = findfather(f[x]);
            if (sdom[son[x]] > sdom[son[f[x]]])
            {
                    son[x] = son[f[x]];
            }
            return  f[x] = y;
    }
    void dfs(int u)
    {
            id[dfn[u] = ++cnt] = u;
            for (int v, i = 0; i < yuantu[u].size(); i++)
            {
                    if (v = yuantu[u][i], !dfn[v])
                    {
                            dfs(v), fa[dfn[v]] = dfn[u];
                    }
            }
    }
    inline void tarjan(int s)
    {
            for (int i = 1; i <= n; i++)
            {
                    f[i] = sdom[i] = son[i] = fa[i] = i;
                    dfn[i] = 0;
            }
            cnt = 0, dfs(s);
            int k, x;
            for (int i = cnt; i > 1; i--)
            {
                    for (int v, j = 0; j < fantu[id[i]].size(); j++)
                    {
                            if (v = fantu[id[i]][j], dfn[v])
                            {
                                    findfather(k = dfn[v]), sdom[i] = sdom[i] < sdom[son[k]] ? sdom[i] : sdom[son[k]];
                            }
                    }
                    zhipei[sdom[i]].push_back(i), f[i] = x = fa[i];
                    for (int v, j = 0; j < zhipei[f[i]].size(); j++)
                    {
                            v = zhipei[f[i]][j], findfather(k = v), idom[k] = sdom[son[k]] < x ? son[k] : x;
                    }
                    zhipei[x].clear();
            }
            for (int i = 2; i <= cnt; zhipei[id[idom[i]]].push_back(id[i]), i++)
            {
                    if (idom[i] != sdom[i])
                    {
                            idom[i] = idom[idom[i]];
                    }
            }
    }
    void mp(int u, int p)
    {
            ans[u] = p;
            for (int v, i = 0; i < zhipei[u].size(); i++)
            {
                    v = zhipei[u][i], mp(v, p + v);
            }
    }
    int main()
    {
            ios_base::sync_with_stdio(0);
            cin.tie(0);
            int T;
            int u, v;
            //freopen("jqkout.txt", "w", stdout);
            while (scanf("%d %d", &n, &m) == 2)
            {
                    for (int i = 0; i <= n; i++)
                    {
                            yuantu[i].clear(), fantu[i].clear(), zhipei[i].clear();
                    }
                    for (int i = 1; i <= m; i++)
                    {
                            scanf("%d %d", &u, &v);
                            yuantu[u].push_back(v), fantu[v].push_back(u);
                    }
                    tarjan(n);
                    mp(n, n);
                    for (int i = 1; i <= n; i++)
                    {
                            cout << ans[i];
                            if (i != n)
                            {
                                    cout << " ";
                            }
                            else
                            {
                                    cout << endl;
                            }
                            ans[i] = 0;
                    }
            }
            return 0;
    }
    View Code

    Opencup Petrozavodsk Winter Training Camp 2018
    Day 8: Saratov SU Contest, Tuesday, February 8, 2018
    Problem L. Increasing Costs 

    求出支配树 支配树上的点在DAG中入度为1的话 那条边则为必经边

    /*Huyyt*/
    #include<bits/stdc++.h>
    #define mem(a,b) memset(a,b,sizeof(a))
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    const double eps = 1e-8;
    const int dir[8][2] = {{0, 1}, {1, 0}, {0, -1}, { -1, 0}, {1, 1}, {1, -1}, { -1, -1}, { -1, 1}};
    const int mod = 1e9 + 7, gakki = 5 + 2 + 1 + 19880611 + 1e9;
    const int MAXN = 1e6 + 5, MAXM = 1e6 + 5;
    const int MAXQ = 100010, INF = 1e9;
    int to[MAXM << 1], nxt[MAXM << 1], Head[MAXN], tot = 1;
    ll cost[MAXM << 1];
    int preedge[MAXN];
    int du[MAXN];
    struct node
    {
            int u, v;
            ll c;
    } edge[MAXM << 1];
    inline void addedge(int u, int v, ll c)
    {
            to[++tot] = v;
            nxt[tot] = Head[u];
            cost[tot] = c;
            Head[u] = tot;
    }
    inline void read(int &v)
    {
            v = 0;
            char c = 0;
            int p = 1;
            while (c < '0' || c > '9')
            {
                    if (c == '-')
                    {
                            p = -1;
                    }
                    c = getchar();
            }
            while (c >= '0' && c <= '9')
            {
                    v = (v << 3) + (v << 1) + c - '0';
                    c = getchar();
            }
            v *= p;
    }
    int dp[MAXN];
    ll dis[MAXN];
    bool visit[MAXN];
    priority_queue < pair<ll, int>, vector<pair<ll, int> >, greater<pair<ll, int> > >que;
    bool chose[MAXM];
    int dfn[MAXN], idom[MAXN], sdom[MAXN];
    int son[MAXN], id[MAXN], fa[MAXN], f[MAXN];
    int ans[MAXN];
    int cnt;
    int n, m;
    vector<int> yuantu[MAXN], fantu[MAXN], zhipei[MAXN];
    int findfather(int x)
    {
            if (f[x] == x)
            {
                    return x;
            }
            int y = findfather(f[x]);
            if (sdom[son[x]] > sdom[son[f[x]]])
            {
                    son[x] = son[f[x]];
            }
            return  f[x] = y;
    }
    void dfs(int u)
    {
            id[dfn[u] = ++cnt] = u;
            for (int v, i = 0; i < yuantu[u].size(); i++)
            {
                    if (v = yuantu[u][i], !dfn[v])
                    {
                            dfs(v), fa[dfn[v]] = dfn[u];
                    }
            }
    }
    inline void tarjan(int s)
    {
            for (int i = 1; i <= n; i++)
            {
                    f[i] = sdom[i] = son[i] = fa[i] = i;
                    dfn[i] = 0;
            }
            cnt = 0, dfs(s);
            int k, x;
            for (int i = cnt; i > 1; i--)
            {
                    for (int v, j = 0; j < fantu[id[i]].size(); j++)
                    {
                            if (v = fantu[id[i]][j], dfn[v])
                            {
                                    findfather(k = dfn[v]), sdom[i] = sdom[i] < sdom[son[k]] ? sdom[i] : sdom[son[k]];
                            }
                    }
                    zhipei[sdom[i]].push_back(i), f[i] = x = fa[i];
                    for (int v, j = 0; j < zhipei[f[i]].size(); j++)
                    {
                            v = zhipei[f[i]][j], findfather(k = v), idom[k] = sdom[son[k]] < x ? son[k] : x;
                    }
                    zhipei[x].clear();
            }
            for (int i = 2; i <= cnt; zhipei[id[idom[i]]].push_back(id[i]), i++)
            {
                    if (idom[i] != sdom[i])
                    {
                            idom[i] = idom[idom[i]];
                    }
            }
    }
    void get_ans(int u)
    {
            dp[u] = 1;
            for (int v, i = 0; i < zhipei[u].size(); i++)
            {
                    v = zhipei[u][i];
                    //cout << u << " " << v << endl;
                    get_ans(v);
                    dp[u] += dp[v];
            }
            if (du[u] == 1)
            {
                    ans[preedge[u]] = dp[u];
            }
    }
    int main()
    {
            ios_base::sync_with_stdio(0);
            cin.tie(0);
    
            int T;
            //freopen("jqkout.txt", "w", stdout);
            int u, v, c;
            read(n), read(m);
            for (int i = 1; i <= m; i++)
            {
                    chose[i * 2] = chose[i * 2 - 1] = false;
                    //scanf("%d %d %d", &u, &v, &c);
                    read(u), read(v), read(c);
                    edge[i * 2 - 1].u = u, edge[i * 2 - 1].v = v, edge[i * 2 - 1].c = c;
                    edge[i * 2].u = v, edge[i * 2].v = u, edge[i * 2].c = c;
                    addedge(u, v, c);
                    addedge(v, u, c);
            }
            for (int i = 1; i <= n; i++)
            {
                    visit[i] = false;
                    dis[i] = LLONG_MAX;
            }
            dis[1] = 0;
            pair<ll, int> cnt;
            que.push(make_pair(0, 1));
            while (!que.empty())
            {
                    cnt = que.top();
                    que.pop();
                    visit[cnt.second] = true;
                    for (int i = Head[cnt.second]; i; i = nxt[i])
                    {
                            int v = to[i];
                            if (visit[v])
                            {
                                    continue;
                            }
                            if (dis[v] > dis[cnt.second] + cost[i])
                            {
                                    dis[v] = dis[cnt.second] + cost[i];
                                    que.push(make_pair(dis[v], v));
                            }
                    }
            }
            //        for (int i = 1; i <= n; i++)
            //        {
            //                cout << dis[i] << " ";
            //        }
            //        cout << endl;
            for (int i = 1; i <= 2 * m; i++)
            {
                    if (dis[edge[i].v] == dis[edge[i].u] + edge[i].c)
                    {
                            //cout << edge[i].u << " " << edge[i].v << endl;
                            chose[i] = true;
                            yuantu[edge[i].u].push_back(edge[i].v);
                            du[edge[i].v]++;
                            preedge[edge[i].v] = (i + 1) / 2;
                            fantu[edge[i].v].push_back(edge[i].u);
                    }
            }
            tarjan(1);
            get_ans(1);
            for (int i = 1; i <= m; i++)
            {
                    cout << ans[i] << endl;
            }
            return 0;
    }
    View Code
  • 相关阅读:
    Windows NT 技术简介
    IOS7上呈现IOS6的水滴刷新效果
    Asp.net HttpWebRequest和HttpWebResponse发送和接受任何类型数据
    QQ互联OAuth2.0 .NET SDK 发布以及网站QQ登陆示例代码
    在PowerDesigner中设计物理模型1——表和主外键
    mantisbt邮件配置
    Mantis安装与配置
    Mime类型与文件后缀对照表及探测文件MIME的方法
    MIME类型-服务端验证上传文件的类型
    SWFUpload 2.5.0版 官方说明文档 中文翻译版
  • 原文地址:https://www.cnblogs.com/Aragaki/p/9357199.html
Copyright © 2020-2023  润新知