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 11 2
样例输出
-
201
#include<stdio.h> #include<string.h> int n,m,x,y; const int maxn=10001; int r[maxn]; int c[maxn]; int a[maxn][301]; int ans[maxn]; int main() { while (scanf("%d%d",&n,&m)==2) { memset(r,0,sizeof(r));//标记入度。 memset(c,0,sizeof(c));//边 memset(a,0,sizeof(a));//标记作用 memset(ans,0,sizeof(ans));//也是标记作用 int tot=0;//计数 ,计算出度的数 int money=0;//钱 int k=0;//增量 int t;//每次的度数为0的数 while(m--) { scanf("%d%d",&x,&y);//y到x的边 r[x]++;//入度加1; c[y]++;//链接边+1 a[y][c[y]]=x;//y代表这个结点练的边,c[y]标记这是y的第几个边,连到x } while (tot<n)//没节点有全部删完 tot代表已删的节点 { t=0; for (int i=1;i<=n;i++) if (!r[i])//如果i节点入度为0,那么存储这个节点并删除 { tot++; t++;//0的度数,也就是比上一层多的人数 ans[t]=i; r[i]=maxn;//删除结点 money+=100; } if (!t) { printf("impossible\n"); break; } money+=k*t;//对于每一个层次补齐差价,k为每个人的差价 k++;//加差价 for (int i=1;i<=t;i++)//点的遍历 { for (int j=1;j<=c[ans[i]];j++)//点对应边的遍历 { r[a[ans[i]][j]]--;//入度减一,下次判断如果是0就出度 } } } if(t) printf("%d\n",money); } return 0; }