奖学金 灵活的拓扑排序

  1. 对先遍历后处理要理解的深刻。
  2. 从下往上遍历通过传参数改变父节点的值。
  3. 利用vector存图可以大大减少空间和时间的开销。

算法一定要灵活的掌握,不能死搬硬套,而且对先遍历后处理的思想理解的要深刻,还有从下往上遍历时通过传参改变父节点值。
利用vector存图可以大大减少空间和时间的开销,但是要resize()哦。
题目:

00030:奖学金
查看 提交 统计 提问
总时间限制: 1000ms 内存限制: 128000kB
描述
期末考试终于完了,老班决定召开班委会,内容嘛,则是可爱的奖学金的问题((*^__^*)),她叫来了一些班委,每位班委提出了自己的意见:“我认为同学a的奖学金应该比b多!”老班决定要找出一种奖学金方案,满足各位班委的意见,且同时使得总奖学金数最少。每位同学奖学金最少为100元且都为整数。

【输入】

    第一行两个整数n,m,表示同学总数和班委意见数n<=10000,m<=20000;

    以下m行,每行2个整数a,b,表示某个班委认为第a号同学奖学金应该比第b号同学高。

输入
第一行两个整数n,m,表示同学总数和班委意见数;
以下m行,每行2个整数a,b,表示某个班委认为第a号同学奖学金应该比第b号同学高。
输出
若无法找到合法方案,则输出“impossible”(不含引号);否则输出一个数表示最少总奖学金。
样例输入
2 1
1 2
样例输出
201
#include<cstdio>
#include<iostream>
#include<sstream>
#include<cstdlib>
#include<cmath>
#include<cctype>
#include<string>
#include<cstring>
#include<algorithm>
#include<stack>
#include<queue>
#include<set>
#include<map>
#include<ctime>
#include<vector>
#include<fstream>
#include<list>

using namespace std;

vector<vector<int> >G;
int visited[10001];
int n,s = 0;
int value[10001];
int indexx;

bool dfs(int child,int parent)
{
    visited[child] = -1;
    vector<int>::iterator it;
    for(it = G[child].begin(); it != G[child].end(); ++it)
    {
        indexx = *it;
        if(visited[indexx] == -1)
            return false;
        else
        {
            if(!visited[indexx])
            {
                if(!dfs(indexx,child))
                    return false;
            }
            else//拓扑排序的灵活处理,<更新>父节点的值
            {
                if(value[indexx]+1 > value[child])
                    value[child] = value[indexx]+1;
            }
        }
    }

    visited[child] = 1;

    s += 100 + value[child];
    if(parent != 0 && value[child]+1 > value[parent])
        value[parent] = value[child] + 1;//思路要严密,更新父节点的值
    return true;
}

bool toposort()
{
    for(int i = 1; i <= n; ++i)
    {
        if(!visited[i] && !dfs(i,0))
           return false;
    }
    return true;
}

int main()
{
    //freopen("F:\\data.txt","r",stdin);//方便调试
//    ios::sync_with_stdio(false);//使cin的读入速度接近于scanf

    G.clear();
    memset(visited,0,sizeof(visited));
    memset(value,0,sizeof(value));

    int m;
    scanf("%d%d",&n,&m);
    G.resize(n+1);

    int a,b;
    for(int i = 1; i <= m; ++i)
    {
        scanf("%d%d",&a,&b);
        G[a].push_back(b);
    }
    if(toposort())
    {
        printf("%d\n",s);
    }
    else
        printf("impossible\n");

    return 0;
}
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值