1、AOV网
首先AOV网是一个有向无环图
在AOV图可以看作一个工程图,每个点看作子工程,有向边代表完成工程的先后顺序,例如:图中要完成8必需先完成5、6.
由此显而易见没有入度的1先完成。而拓扑排序就是输出AOV网中的完成先后顺序。
2、拓扑排序
注意:拓扑排序仅适用AOV网(即有向无环图)
算法思路:
1、先找到一个入度为0的点输出。
2、将这个点连向的点的入都减1
3、重复直至无入度为0的点
4、判断判断是否输出了全部点,若未输出全部点则含有环
伪代码:
int a[1000][301]={0};//a[i][j]表示i通向的第j条边 int into[10001];//入度 int ans[10001];//栈 int m,n;//边数,点数 void init()//输入函数 { int i,x,y; cin>>n>>m; for(i=1;i<=m;i++) { cin>>x>>y;//输入x通向y的边 a[x][0]++;//表示有几条边 a[x][a[x][0]]=y ;//输入终点 into[y]++;//入度++ } } bool topsort()//拓扑排序 { int t;//判断是否有环 int tot;//栈指针 while(tot<n) { t=0; for(int i=1;i<=n;i++) if(into[i]=0)//找入度为0的点 { tot++;ans[t]=i;//入栈 t++; into[i]=0xfffffff; } if(t==0) return false;//存在环 for(int i=1;i<=t;i++) for(int j=1;j<=a[ans[i]][0];j++) into[a[ans[i]][j]]--;//减去通向的边 } return true; } int main() { init(); if(topsort()) for(int i=1;i<=tot;i++) cout<<ans[i]; else cout<<"error"; }
1352:【例4-13】奖金
时间限制: 1000 ms 内存限制: 65536 KB
提交数: 4580 通过数: 1678
【题目描述】
由于无敌的凡凡在2005年世界英俊帅气男总决选中胜出,Yali Company总经理Mr.Z心情好,决定给每位员工发奖金。公司决定以每个人本年在公司的贡献为标准来计算他们得到奖金的多少。
于是Mr.Z下令召开m方会谈。每位参加会谈的代表提出了自己的意见:“我认为员工a的奖金应该比b高!”Mr.Z决定要找出一种奖金方案,满足各位代表的意见,且同时使得总奖金数最少。每位员工奖金最少为100元。
【输入】
第一行两个整数n,m,表示员工总数和代表数;
以下m行,每行2个整数a,b,表示某个代表认为第a号员工奖金应该比第b号员工高。
【输出】
若无法找到合理方案,则输出“Poor Xed”;否则输出一个数表示最少总奖金。
【输入样例】
2 1
1 2
【输出样例】
201
【提示】
【数据规模】
80%的数据满足:n≤1000,m≤2000;
100%的数据满足:n≤10000,m≤20000。
#include<cstdio> #include<iostream> using namespace std; int a[10001][301]={0},into[10001],ans[10001],m,n,money; void init() { int i,x,y; cin>>n>>m; for(i=1;i<=m;i++) { cin>>x>>y; a[y][0]++; a[y][a[y][0]]=x; into[x]++; } } bool topsort() { int t,tot,k,i,j; tot=0;k=0; while(tot<n) { int t=0; for(int i=1;i<=n;i++) if(into[i]==0){ tot++;t++;money+=100; ans[t]=i; into[i]=0xfffffff; } if(t==0) return false; money+=k*t;k++; for(i=1;i<=t;i++) for(j=1;j<=a[ans[i]][0];j++) into[a [ ans[i] ] [j]]--; } return true; } int main() { init();money=0; if(topsort())cout<<money<<endl; else cout<<"Poor Xed"<<endl; return 0; }