zoukankan      html  css  js  c++  java
  • 《省赛模拟赛补》

    C题:

    比赛的时候已经想到了统计最底层的每个序列的出现次数,但是一开始想的是建图之后dfs处理,但是发现很难处理出来。

    其实正确的思路是拓扑排序去处理次数。

    我们在最后建图完成之后,倒着从n回去拓扑即可。

    但是这里有个坑点,就是一开始统计入度可能是不正确的。

    例如:3(1 , 2), 4 (1 ,2),3是1,2的父节点,4是1,2的父节点,这样的话,我们拓扑的时候1,2的入度就不可能减到2了,因为我们最终的序列是s4,所以我们只去考虑和4相关。

    所以对于入度的统计,我们需要从终点bfs去重新计算入度,然后再拓扑即可。

    这里cnt忘开longlong被卡了一会。。

    最后就是复杂度的证明:

    可以发现,拓扑和bfs的复杂度显然也就1e6左右,主要是可能会觉得最后map统计那里会T,但是实际上,map统计那里,我们只是进行了一个对输入的重新遍历(加了个log的复杂度,还是很快的),如果输入不会T,显然这里也不会。

    (输入怎么可能会T~~)

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    typedef pair<double,int> pii;
    const int N = 1e6+5;
    const int M = 1e6+5;
    const LL Mod = 1e9+7;
    #define rg register
    #define pi acos(-1)
    #define INF 1e18
    #define CT0 cin.tie(0),cout.tie(0)
    #define IO ios::sync_with_stdio(false)
    #define dbg(ax) cout << "now this num is " << ax << endl;
    namespace FASTIO{
        inline LL read(){
            LL x = 0,f = 1;char c = getchar();
            while(c < '0' || c > '9'){if(c == '-') f = -1;c = getchar();}
            while(c >= '0' && c <= '9'){x = (x<<1)+(x<<3)+(c^48);c = getchar();}
            return x*f;
        }
        void print(int x){
            if(x < 0){x = -x;putchar('-');}
            if(x > 9) print(x/10);
            putchar(x%10+'0');
        }
    }
    using namespace FASTIO;
    
    vector<int> a[N],G[N];
    int vis[N],id[N];
    LL cnt[N],in[N];
    void bfs(int n)
    {
        queue<int> Q;
        Q.push(n);
        vis[n] = 1;
        while(!Q.empty())
        {
            int u = Q.front();
            Q.pop();
            for(auto v : G[u])
            {
                in[v]++;
                if(!vis[v]) vis[v] = 1,Q.push(v);
            }
        }
    }
    void solve(int n)
    {
        queue<int> Q;
        Q.push(n);
        cnt[n] = 1;
        while(!Q.empty())
        {
            int u = Q.front();
            Q.pop();
            for(auto v : G[u])
            {
                in[v]--;
                cnt[v] += cnt[u];
                if(in[v] == 0) Q.push(v);
            }
        }
        unordered_map<int,LL> mp;
        LL mx = -1,sum = 0;
        for(rg int i = 1;i <= n;++i)
        {
            if(id[i] == 2 || cnt[i] == 0) continue;
            for(auto v : a[i])
            {
                mp[v] += cnt[i];
                sum += cnt[i];
                mx = max(mx,mp[v]);
            }
        }
        LL ma = sum - mx;
        printf("%lld
    ",mx <= ma ? sum : ma * 2);
    }
    int main()
    {
        int ca;ca = read();
        while(ca--)
        {
            int n;n = read();
            for(rg int i = 1;i <= n;++i) in[i] = 0,cnt[i] = 0,G[i].clear(),a[i].clear(),vis[i] = 0;
            for(rg int i = 1;i <= n;++i)
            {
                int idd;idd = read();
                id[i] = idd;
                if(idd == 1)
                {
                    int k;k = read();
                    while(k--)
                    {
                        int x;x = read();
                        a[i].push_back(x);
                    }
                }
                else 
                {
                    int x,y;x = read(),y = read();
                    G[i].push_back(x);
                    G[i].push_back(y);
                }
            }
            bfs(n);
            solve(n);
        }    
        system("pause");
        return 0;
    }
    /*
    4
    4
    1 2 2 2
    1 2 2 4
    2 1 2
    2 1 2
    
    */
    View Code
  • 相关阅读:
    jar 命令 打包装class文件的文件夹
    快捷下载 sourceForge下的资源
    win7 解决git clone 连接被拒绝—hosts文件过期
    tp_link路由器 重新设置
    gradle研究
    开始玩mondrian
    让eclipse启动时拥有jre
    qt md5加密,base64编码解码
    qt 网络库使用介绍
    c 正则表达式
  • 原文地址:https://www.cnblogs.com/zwjzwj/p/13800901.html
Copyright © 2011-2022 走看看