小测题解

奖学金

总间限制:
1000ms
内存限制:
128000kB
描述

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

【输入】

    第一行两个整数n(0<=n<=10,000),m(0<=m<=20,000),表示同学总数和班委意见数;

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

输入
第一行两个整数n,m,表示同学总数和班委意见数;
以下m行,每行2个整数a,b,表示某个班委认为第a号同学奖学金应该比第b号同学高。
输出
若无法找到合法方案,则输出“impossible”(不含引号);否则输出一个数表示最少总奖学金。
样例输入
2 11 2
样例输出
201
 
分析:
	对于所有给出的限制例如 a的奖学金一定比b的高,则建一条由b到a的有向边
	如此,只要每一次从入度为零的点进行拓扑排序就可以了;
	也方便了进行判环的操作
代码如下
 
 
#include<cstring>
#include<cstdio>
#include<queue>
using namespace std;
inline void read(int &x){
	x=0;char ch;
	while(ch=getchar(),ch<'!');
	while(x=10*x+ch-'0',ch=getchar(),ch>'!');
}
inline int cat_max(const int &a,const int &b){return a>b ? a:b;}
inline int cat_min(const int &a,const int &b){return a<b ? a:b;}
const int maxn = 10000 + 10;
struct node{
    int num;
    int mon; 
    node ():num(0),mon(100){};  
}G[maxn];
struct Edge{
	int to,next;
}g[20000 + 10];
int head[maxn],tot=0;
void add(int u,int v){
	g[++tot].to = v;
	g[tot].next = head[u];
	head[u] = tot; 
}
int cnt=0;
int q[maxn],l=0,r=0;
int main(){
//	freopen("reward.in","r",stdin);
//	freopen("reward.out","w",stdout);
    int n,m;read(n);read(m);
    bool flag = true;int a,b;
    while(m--){
        read(a),read(b);
        add(b,a);
        G[a].num++;//纪录每一个点的入度 
    }
    for (int i = 1; i <= n; i++){
        if (G[i].num == 0){
            q[r] = i;
			 ++r;
        }
    }
    int tmp;
    while (l<r){
        tmp = q[l];++l;
        for(int i = head[tmp]; i ; i = g[i].next){
            G[g[i].to].num--;
            if(G[g[i].to].mon <= G[tmp].mon)
               G[g[i].to].mon = G[tmp].mon + 1;
            if(G[g[i].to].num == 0){//入度为零则不可能再一次被更新了 
                q[r] = g[i].to ; ++r;
            }
        }
    }
    for (int i = 1; i <= n; i++){
        if (G[i].num != 0){
           flag = false;
           break;//判环 
        }
        cnt += G[i].mon;
    }
    if (!flag) printf("impossible");
    else printf("%d", cnt);
    fclose(stdin);fclose(stdout);return 0;
}             

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值