2022 Shanghai Collegiate Programming Contest - M. My University Is Better Than Yours 缩点+dp

M. My University Is Better Than Yours

题目描述

People rank for things. Yes, ranking is nothing for most of the time, except when you are doing year-end report to your boss.

Under the promotion of the construction of world-class universities, a lot of universities are struggling to improve ranking in every way. Publishing papers, applying for funds, improving diversity… They are too hard and your result may not be fairly judged by institutions like US News and Times! However, some universities are more clever – they publish their own rankings, which makes the ranking indirectly better. For example, using Shanghai Ranking’s Academic Ranking of World Universities (ARWU) produced by Shanghai Jiao Tong University, Desprado2 can prove that his school is better than MIT.
https://www.zizhengfang.com/applets/transitivity
Anyway, that is a joke unless you are finding jobs and need to brag about your school. But at the same time, Desprado2 comes out a problem: assume there are n n n universities in total, and he has collected m university rankings. For simplicity, all the universities are denoted by a number from 1 1 1 to n n n. Here, Desprado2 defines that university x x x is directly better than university y, if and only if there exists a university ranking such that university x x x ranks higher than university y y y. Furthermore, Desprado2 defines that university x x x is b e t t e r better better than university y y y, if and only if there exists a sequence {s1, s2, …, sk} (k≥2), such that:

s 1 = x , s k = y s_1=x, s_k=y s1=x,sk=y
∀i∈{1,2,…,k−1}, university si is directly better than university s i + 1 s_{i+1} si+1
For each university, Desprado2 want you to tell him it is better than how many of other universities.
输入描述

The first line contains two integers n n n and m ( 1 ≤ n ≤ 5 × 1 0 5 , 1 ≤ m ≤ 5 × 1 0 5 , 1 ≤ n × m ≤ 1 0 6 ) m (1≤n≤5×10^5, 1≤m≤5×10^5, 1≤n×m≤10^6) m(1n5×105,1m5×105,1n×m106), denoting the number of universities considered, and the number of university rankings.

Then follows m m m lines. The i i i-th line contains n distinct integers s i , 1 , s i , 2 , . . . , s i , n si,1, si,2, ..., si,n si,1,si,2,...,si,n ( 1 ≤ s i , j ≤ n ) (1≤si,j≤n) (1si,jn), denoting the order of the i i i-th university ranking (from high to low).

输出描述

Output one line with n n n integers a 1 , a 2 , … , a n a1,a2,…,an a1,a2,,an, separated by spaces. The i i i-th number a i a_i ai denotes the number of universities that university i i i is better than.

输入样例1:

4 2
1 2 3 4
1 3 2 4

输出样例1:

3 2 2 0

输入样例2:

4 2
1 2 3 4
4 3 2 1

输出样例2:

3 3 3 3

输入样例3:

5 2
5 4 3 2 1
5 4 3 2 1

输出样例3:

0 1 2 3 4

思路

题目中的直接大于意味着大于这所学校即大于这所学校所大于的所有学校 故我们可以将相邻的两所学校连边建图 再缩点将图转化为 D A G DAG DAG 图 设每个点权值为 1 1 1 求以每个点为首除去自身点的最大权值路径 d p [ i ] dp[i] dp[i]

Code

#include<bits/stdc++.h>
using namespace std;
#define __T int csT;scanf("%d",&csT);while(csT--)
const int mod=998244353;
const int maxn=5e5+3;
const int maxm=1e6+3;

//Kosaraju:O(n+m)
//需建新图的情况 加上fr[maxn]代表fr[x]属于哪个强连通分量
//并且需要记录原始边 u[] v[]
int n,m,cnt,flcnt;//flcnt 新点/强连通分量个数
int stcnt,st[maxn];//模拟栈 存储逆后序 
int h[maxn],rh[maxn];//正反图
int nm,nh[maxn],na[maxn];//新图
int a[maxn],vis[maxn],fr[maxn],dp[maxn];
int u[maxm],v[maxm];//原始边
struct node
{
    int to,nx;
}e[maxm],re[maxm],ne[maxm];
void dfs1(int at)
{
    if(vis[at]==1)return;
    vis[at]=1;
    for(int i=h[at];~i;i=e[i].nx)
    {
        dfs1(e[i].to);
    }
    st[++stcnt]=at;
}//先跑一遍正图以得到跑反图时的顺序序列
void dfs2(int at,int id)
{
    if(vis[at]==2)return;
    vis[at]=2;
    fr[at]=id;
    na[id]+=a[at];//统计该强连通分量的权值和
    for(int i=rh[at];~i;i=re[i].nx)
    {
        dfs2(re[i].to,id);
    }
}
void dfs3(int at)
{
    if(dp[at]!=-1)return;
    dp[at]=0;
    for(int i=nh[at];~i;i=ne[i].nx)
    {
        dfs3(ne[i].to);
        dp[at]=max(dp[at],dp[ne[i].to]);
    }
    dp[at]+=na[at];
}
inline void sol()
{
    scanf("%d%d",&n,&m);
    memset(h,-1,sizeof h);
    memset(rh,-1,sizeof rh);
    memset(nh,-1,sizeof nh);
    memset(vis,0,sizeof vis);
    memset(na,0,sizeof na);
    stcnt=cnt=nm=flcnt=0;
    for(int i=1;i<=n;++i)
    {
        a[i]=1;
    }
    int q,x,mcnt=0;
    for(int i=0;i<m;++i)
    {
        q=-1;
        for(int j=1;j<=n;++j)
        {
            scanf("%d",&x);
            if(q==-1)
            {
                q=x;
                continue;
            }
            u[++mcnt]=q;
            v[mcnt]=x;
            e[++cnt].to=v[mcnt];
            e[cnt].nx=h[u[mcnt]];
            h[u[mcnt]]=cnt;
            re[cnt].to=u[mcnt];
            re[cnt].nx=rh[v[mcnt]];
            rh[v[mcnt]]=cnt;//建正图反图
            q=x;
        }
    }
    for(int i=1;i<=n;++i)
    {
        if(vis[i]==0)dfs1(i);
    }
    for(int i=n;i>=1;--i)
    {
        if(vis[st[i]]==1)
        {
            dfs2(st[i],++flcnt);
        }
    }
    for(int i=1;i<=mcnt;++i)
    {
        if(fr[u[i]]!=fr[v[i]])//筛去缩点后的自环
        {
            ne[++nm].to=fr[v[i]];
            ne[nm].nx=nh[fr[u[i]]];
            nh[fr[u[i]]]=nm;
        }
    }
    memset(dp,-1,sizeof dp);
    for(int i=1;i<=flcnt;++i)
    {
        if(dp[i]==-1)
        {
            dfs3(i);
        }
    }
    for(int i=1;i<=n;++i)
    {
        printf("%d ",dp[fr[i]]-1);
    }
    puts("");
}

int main()
{
    //__T
    sol();
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

柯西可乐

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值