《省赛模拟赛补》

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\n",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

 

posted @ 2020-10-12 09:15  levill  阅读(174)  评论(0编辑  收藏  举报