Skip to content

T22508: 最小奖金方案

topologic sort, http://cs101.openjudge.cn/practice/22508/

【姚博骞 25物院】思路:构建图,记录出度和入度的来源数组,这个学期也可以学习一下基本图论,以前没怎么搞过数学竞赛。 关键的转移方程: prize[beatenby[i][j]]=max(prize[beatenby[i][j]],prize[i]+1);

cpp
#include<iostream>
#include<queue>
#include<vector>
#include<unordered_map>
using namespace std;
int max(int a,int b)
{
    return (a>b)?a:b;
}
int main()
{
    //记录每个队伍打败的队伍数量,以及被打败的队伍的集合
    //考虑拓扑排序,肯定要一个也没打败的,直接把打败他的队伍奖金都变成max(now,ta+1),然后踢出去。
    int n,m;
    cin>>n>>m;
    vector<pair<int,int>>pk;
    vector<int> prize(n,100);
    for(int i=0;i<m;i++)
    {
        int a,b;
        cin>>a>>b;
        pk.push_back({a,b});
    }
    //构建图
    vector<int>num_beat(n,0);
    vector<vector<int>>beatenby(n,vector<int>(0));
    for(int i=0;i<m;i++)
    {
        num_beat[pk[i].first]++;
        beatenby[pk[i].second].push_back(pk[i].first);
    }
    queue<int>q;
    for(int i=0;i<n;i++)
    {
        if(!num_beat[i]) q.push(i);
    }
    while(!q.empty())
    {
        int i=q.front();
        q.pop();
        for(int j=0;j<beatenby[i].size();j++)
        {
            num_beat[beatenby[i][j]]--;
            prize[beatenby[i][j]]=max(prize[beatenby[i][j]],prize[i]+1);
            if(num_beat[beatenby[i][j]]==0) q.push(beatenby[i][j]);
        }
    }
    int ans=0;
    for(int i=0;i<n;i++)
    {
        ans+=prize[i];
    }
    cout<<ans;
    return 0;
}