- 对先遍历后处理要理解的深刻。
- 从下往上遍历通过传参数改变父节点的值。
- 利用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;
}