奖学金
- 总间限制:
- 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; }