90分求助,#9TLE

P1983 [NOIP2013 普及组] 车站分级

zhibuba @ 2020-08-21 17:16:17

#include <iostream>
#include <algorithm>
#include <vector>
#include <unordered_set>
#include <queue>
#include <iterator>

using namespace std;

unordered_set<int> G[1001];
int grade[1001], indegree[1001];
int n, m;

void build_graph()
{
    cin >> n >> m;
    while (m--)
    {
        int s;
        cin >> s;
        vector<int> a(s), b;
        copy_n(istream_iterator<int>(cin), s, begin(a));
        for (int i = a.front(), j = 0; i <= a.back(); i++)
        {
            if (i == a[j])
                j++;
            else
            {
                for (int v : a)
                    indegree[v] += G[i].insert(v).second;
            }
        }
    }
}

int ans;
queue<int> Q;
void topsort()
{
    for (int i = 1; i <= n; i++)
    {
        if (indegree[i] == 0)
        {
            Q.push(i);
            grade[i] = 1;
        }
    }
    while (!Q.empty())
    {
        int a = Q.front();
        Q.pop();
        for (auto b : G[a])
        {
            indegree[b]--;
            grade[b] = max(grade[b], grade[a] + 1);
            if (indegree[b] == 0)
                Q.push(b);
        }
        ans = max(ans, grade[a]);
    }
}

int main()
{
    ios::sync_with_stdio(false);
    build_graph();
    topsort();
    cout << ans;
    return 0;
}

by do_while_true @ 2020-08-21 17:35:35

@zhibuba 直接连边的复杂度不对吧


by do_while_true @ 2020-08-21 17:36:16

这个题的一半题解都是错的吧


by do_while_true @ 2020-08-21 17:38:11

此题跑拓扑排序的正确连边方法是建立虚拟节点,或者线段树优化建图


by zhibuba @ 2020-08-22 23:23:32

@do_while_true 虚拟节点是怎么弄?


by do_while_true @ 2020-08-22 23:44:03

@zhibuba 可以参考我这份代码

虚拟节点单独开出来,标记哪些节点是虚拟节点,在拓扑排序的时候遇到虚拟节点不更新答案。

#include<iostream>
#include<cstdio>
#include<queue>
#define mp std::make_pair
#define pp std::pair<int,int>
const int N=10100;
inline int read()
{
    int r=0,w=0;
    char ch=getchar();
    while(ch<'0'||ch>'9') {
        if(ch=='-') w=1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9') {
        r=(r<<3)+(r<<1)+(ch^48);
        ch=getchar();
    }
    return w ? ~r+1 : r;
}
int n,m,num;
int f[N<<1],ans,in[N<<1];
int fl[N<<1];
int cnt,head[N<<1];
struct node {
    int to,nxt;
}e[N*N<<1];
int s[N],vis[N];
std::queue<int>q; 
void add(int x,int y)
{
    e[++cnt].to=y;
    e[cnt].nxt=head[x];
    head[x]=cnt;
    in[y]++;
}
int main()
{
    n=read();m=read();
    num=n;
    for(int i=1;i<=m;i++) {
        int k=read();
        int bnt=0;
        for(int j=1;j<=k;j++)
            s[j]=read();
        for(int j=s[1];j<=s[k];j++)
            vis[j]=0;
        for(int j=1;j<=k;j++)
            vis[s[j]]=1,bnt++;
        if(bnt==s[k]-s[1]+1) continue;
        ++num;
        fl[num]=1; 
        for(int j=s[1];j<=s[k];j++) {
            if(!vis[j])
                add(j,num);
            else
                add(num,j);
        }
    }
    for(int i=1;i<=num;i++)
        if(!in[i])
            q.push(i),f[i]=1;
    while(!q.empty()) {
        int now=q.front();
        q.pop();
        ans=std::max(ans,f[now]);
        for(int i=head[now];i;i=e[i].nxt) {
            in[e[i].to]--;
            f[e[i].to]=std::max(f[e[i].to],f[now]+(fl[e[i].to] ? 0 : 1 ));
            if(!in[e[i].to])
                q.push(e[i].to);
        }
    }
    printf("%d",ans);
    return 0;
}

by do_while_true @ 2020-08-22 23:45:04

如果对代码哪里有疑问可以问我


by zhibuba @ 2020-08-22 23:58:14

@do_while_true 懂了,多谢


by theHermit @ 2020-08-29 09:34:09

@do_while_true

非常感谢~

对蒟蒻(我)特别有帮助!~


|