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