一.定义对一个有向无环图(Directed Acyclic Graph简称DAG)G进行拓扑排序,是将G中所有顶点排成一个线性序列,使得图中任意一对顶点u和v,若边(u,v)∈E(G),则u在线性序列中出现在v之前。通常,这样的线性序列称为满足拓扑次序(Topological Order)的序列,简称拓扑序列。简单的说,由某个集合上的一个偏序得到该集合上的一个全序,这个操作称之为拓扑排序。
二.实现
1.在有向图中选择一个没有前驱的顶点并且输出(入度为零)
2.从图中删除给定点和所有出边
3.重复上面的操作,知道所有的点都输出,或者当前图中不存在无前前驱的顶点,后者代表我们的有向图时有环的。因此也可以通过拓扑排序来判断一个图是否有环。
例题:http://hihocoder.com/problemset/problem/1174#
拓扑排序只需要关心他的入度;
该题代码如下:
int T, n, m, u, v, num;
vector<int>ve[maxn];
queue<int>q;
int InDeg[maxn];
bool topsort(){
num = 0;
while(!q.empty())q.pop();
for(int i = 1; i <= n; i++){
if(InDeg[i] == 0)q.push(i);
}
while(!q.empty()){
int a = q.front();
q.pop();
num ++;
for(int i = 0; i < ve[a].size(); i++){
if(--InDeg[ve[a][i]] == 0) q.push(ve[a][i]);
}
}
if(num == n) return true;
else return false;
}
int main(){
ios::sync_with_stdio(false);
cin >> T;
while(T--){
cin >> n >> m;
memset(InDeg, 0, sizeof(InDeg));
for(int i = 1; i <= n; i++) ve[i].clear();
for(int i = 1; i <= m; i++){
cin >> u >> v;
ve[u].push_back(v);
InDeg[v]++;
}
if(topsort())cout << "Correct" << endl;
else cout << "Wrong" << endl;
}
return 0;
}
第二道例题:http://hihocoder.com/problemset/problem/1175
代码如下:
int n, m, k, u, v, ans;
int a[maxn];
int num[maxn];
int InDeg[maxn];
vector<int>ve[maxn];
queue<int>q;
void count(){
while(!q.empty())q.pop();
for(int i = 1; i <= n; i++){
if(!InDeg[i])q.push(i);
}
while(!q.empty()){
int a = q.front();
q.pop();
for(int i = 0; i < ve[a].size(); i++){
if(--InDeg[ve[a][i]] == 0)q.push(ve[a][i]);
num[ve[a][i]] = (num[ve[a][i]] + num[a])%mod;
}
}
}
int main(){
ios::sync_with_stdio(false);
cin >> n >> m >> k;
for(int i = 1; i<= n; i++)ve[i].clear();
memset(num, 0, sizeof(num));
memset(InDeg, 0, sizeof(InDeg));
for(int i = 0; i < k; i ++){
cin >> a[i];
num[a[i]]++;
}
for(int i = 0; i < m; i ++){
cin >> u >> v;
ve[u].push_back(v);
InDeg[v]++;
}
count();
ans = 0;
for(int i = 1; i <= n; i++) ans = (ans + num[i])%mod;
cout << ans << endl;
return 0;
}
第三题,拓扑排序含有边权;https://nanti.jisuanke.com/t/A1254
代码如下:
int T, n, m, u, v, w;
vector<pair<int, int> >ve[maxn];
queue<int>q;
int InDeg[maxn];
int dp[maxn];
void topsort(){
while(!q.empty())q.pop();
for(int i = 1; i <= n; i++){
if(!InDeg[i])q.push(i);
}
while(!q.empty()){
int a = q.front();
q.pop();
for(int i = 0; i < ve[a].size(); i++){
if(--InDeg[ve[a][i].first]==0)q.push(ve[a][i].first);
dp[ve[a][i].first] = max(dp[ve[a][i].first], dp[a]+ve[a][i].second);
}
}
}
int main(){
scanf("%d",&T);
while(T--){
scanf("%d%d",&n, &m);
memset(InDeg, 0, sizeof(InDeg));
memset(dp, 0, sizeof(dp));
for(int i = 1; i <= n; i++)ve[i].clear();
for(int i = 0; i < m; i++){
scanf("%d%d%d",&u, &v, &w);
ve[u].push_back(make_pair(v, w));
InDeg[v]++;
}
topsort();
int maxx = -1;
for(int i = 1; i <= n; i++) maxx = max(maxx, dp[i]);
cout << maxx << endl;
}
return 0;
}
第四题:http://codeforces.com/problemset/problem/915/D当做练习题吧。