zoukankan      html  css  js  c++  java
  • UVALive-5731

    UVALive-5731

    题意

    一颗 n - 1 条边的有向树,要求整棵树成为强连通图,一次操作即构建一条路(一笔画),
    限制:

    • 新建的路上的所有边必须与原有的边逆向,即构建的路必须在原有的边和点上,
    • 操作构建的路可以存在公共边或公共点,
    • 一次操作构建的路只能有同一点或边一次

    分析

    要成为强连通图,那么在建边的时候肯定是正反边都要建了,
    up[i] ,表示从 子节点 到 当前节点 i 要有多少条向上的边;
    down[i] ,表示从 当前节点 i 到 子节点 要有多少条向下的边;

    对1这个节点,up[1] = 1,因为实际有一条从 1 到 2 的边,那么新建的边就是 2 -> 1 的这条边;

    结合这个例子模拟一下就好懂了,
    从 0 开始向下搜索,
    先搜到 4 之后回到 3 ,显然 4 -> 3 建边,那么 up[3] = 1 ,
    再去搜 5 再回到 3 ,此时 5 -> 3 建边,那么 up[3] = 2,
    回到 2 ,那么 up[2] = max(1, up[3]) = 2 ,
    再去搜 1 ,回到 2,2 -> 1 建边,down[2] = 1,
    关键来了,此时 min(up[2], down[2]) > 0 ,说明可以直接从 4 向 1 建一条路,然后 up[2]-- ,down[2]-- ,ans++;
    多的 up[] down[] 继续向上传递即可,最后答案加上 max(up[0], down[0]);

    对于这种情况,从 0 开始搜,搜到 2 后回到 1,up[1] = 1,在回到 0 ,down[0] = 1,在得到 down[0] 的值的时候注意了,ans 要直接加上 up[1] 的值,因为up[1] 无法向上传递了,所以当边的方向产生交替的时候,就要处理那些无法向上传递的值;

    code

    #include<bits/stdc++.h>
    using namespace std;
    const int MAXN = 2e4 + 10;
    typedef pair<int, int> P;
    vector<P> G[MAXN];
    int up[MAXN];
    int down[MAXN];
    int ans;
    void dfs(int pre, int u)
    {
        for(int i = 0; i < G[u].size(); i++)
        {
            P v = G[u][i];
            if(v.first == pre) continue;
            dfs(u, v.first);
            if(v.second)
            {
                up[u] += max(1, up[v.first]);
                ans += down[v.first];
            }
            else
            {
                down[u] += max(1, down[v.first]);
                ans += up[v.first];
            }
        }
        int tmp = min(up[u], down[u]);
        up[u] -= tmp; down[u] -= tmp;
        ans += tmp;
    }
    int main()
    {
        int T, c = 1;
        scanf("%d", &T);
        while(T--)
        {
            memset(G, 0, sizeof G);
            memset(up, 0, sizeof up);
            memset(down, 0, sizeof down);
            ans = 0;
            int n;
            scanf("%d", &n);
            for(int i = 1; i < n; i++)
            {
                int x, y;
                scanf("%d%d", &x, &y);
                G[x].push_back(P(y, 1));
                G[y].push_back(P(x, 0));
            }
            dfs(-1, 0);
            printf("Case %d: %d
    ", c++, ans + max(up[0], down[0]));
        }
        return 0;
    }
    
  • 相关阅读:
    POJ 3693 Maximum repetition substring (寻找重复次数最多的连续子串)
    URAL-1297 Palindrome (最长回文子串)
    SPOJ
    POJ Musical Theme (求最长不重叠子串)
    Leangoo看板Jenkins配置指南
    Leangoo(领歌)企业版发布,助力企业规模化敏捷
    推荐Scum敏捷开发的几款工具
    如何使用Leangoo进行简单的BUG管理
    轻量级的项目管理工具-Leangoo
    Leangoo敏捷项目协作工具到底好在哪里?
  • 原文地址:https://www.cnblogs.com/ftae/p/6815064.html
Copyright © 2011-2022 走看看