一般拓扑排序
#include<iostream>
#include<queue>
#include<cstring>
using namespace std;
typedef long long ll;
const int maxn = 1000 + 100;
struct node{
int to, next;
}e[maxn*2];
int head[maxn], cnt;
int deg[maxn];
int a[maxn], len;
int n, m;
void addedge(int u,int v){
e[cnt].to = v; deg[v]++;
e[cnt].next = head[u]; head[u] = cnt++;
}
void init(){
cnt = len = 0;
memset(head, -1, sizeof head);
memset(e, 0, sizeof e);
memset(deg, 0, sizeof deg);
}
void topsort(){
queue<int> q;
for(int i = 1; i <= n;i++)
if(deg[i] == 0) q.push(i);
while(q.size()){
int u = q.front(); q.pop();
a[++len] = u;
for(int i = head[u]; ~i; i = e[i].next){
if(--deg[e[i].to] == 0) //邻点的度减一,并判断是否为0
q.push(e[i].to);
}
}
}
int main()
{
cin>>n>>m;
int u, v;
init();
for(int i = 0; i < m; i++){
cin>>u>>v;
addedge(u,v);
}
topsort();
for(int i = 1;i <= n; i++)
cout<<a[i]<<' ';
return 0;
}
应用一:字典序最小的拓扑排序
题目来源:hdu1285
用小顶推维护就好了
#include<iostream>
#include<queue>
#include<cstring>
using namespace std;
typedef long long ll;
const int maxn = 1000 + 100;
struct node{
int to, next;
}e[maxn*2];
int head[maxn], cnt;
int deg[maxn];
int a[maxn], len;
int n, m;
void addedge(int u,int v){
e[cnt].to = v; deg[v]++;
e[cnt].next = head[u]; head[u] = cnt++;
}
void init(){
cnt = len = 0;
memset(head, -1, sizeof head);
memset(e, 0, sizeof e);
memset(deg, 0, sizeof deg);
memset(a, 0, sizeof a);
}
void topsort(){
priority_queue<int,vector<int>,greater<int> > q;
for(int i = 1; i <= n;i++)
if(deg[i] == 0) q.push(i);
while(q.size()){
int u = q.top(); q.pop();
//cout<<u<<endl;
a[++len] = u;
for(int i = head[u]; ~i; i = e[i].next){
if(--deg[e[i].to] == 0) //邻点的度减一,并判断是否为0
q.push(e[i].to);
}
}
}
int main()
{
while(cin>>n>>m){
int u, v;
init();
for(int i = 0; i < m; i++){
cin>>u>>v;
addedge(u,v);
}
topsort();
for(int i = 1;i < n; i++)
cout<<a[i]<<' ';
cout<<a[n]<<endl;
}
return 0;
}
应用二:判断有向图是否存在环
#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
const int maxn = 1000 + 10;
struct node{
int to, next;
}e[maxn*4]; //在图里面不止2倍
int head[maxn], cnt;
int deg[maxn];
int a[maxn], len;
int n, m;
void init(){
cnt = len = 0;
memset(e, 0, sizeof e);
memset(a, 0, sizeof a);
memset(deg, 0, sizeof deg);
memset(head, -1, sizeof head);
}
void addedge(int u,int v){
e[cnt].to = v; deg[v]++;
e[cnt].next = head[u]; head[u] = cnt++;
}
bool topsort(){
queue<int> q;
for(int i = 1; i <= n; i++)
if(deg[i] == 0) q.push(i);
while(q.size()){
int u = q.front(); q.pop();
a[++len] = u;
for(int i = head[u]; ~i; i = e[i].next)
if(--deg[e[i].to] == 0)
q.push(e[i].to);
}
if(len < n) return false; //还有点没有被遍历到
return true;
}
int main()
{
cin>>n>>m;
int u, v;
init();
for(int i = 1; i <= m; i++){
cin>>u>>v;
addedge(u, v);
}
bool res = topsort();
if(res == false)
cout<<"存在环"<<endl;
else
cout<<"没有环"<<endl;
return 0;
}
实战一:产生冠军
题目描述:有一群人在比赛,有
n
n
n 次斗争,
p
1
p1
p1 赢
p
2
p2
p2,判断是否有冠军,有输出Yes
,否则输出No
。
解题思路:这些人竞争关系构成有向图,并统计每个点的入度。如果存在两个入度为
0
0
0 的点,说明不存在冠军;如果不存在入度为
0
0
0 的点,说明整体构成环,也不存在。即有且只有一个度为
0
0
0 的点。
题目来源:hdu2094
#include<iostream>
#include<cstring>
#include<queue>
#include<string>
#include<map>
using namespace std;
typedef long long ll;
const int maxn = 1000 + 10;
struct node{
int to, next;
}e[maxn*4];
int head[maxn], cnt;
int a[maxn], len;
int deg[maxn];
int n, num;
map<string,int> m;
map<string,int>::iterator it;
void init(){
cnt = len = num = 0;
memset(e, 0, sizeof e);
memset(head, -1, sizeof head);
memset(a, 0, sizeof a);
memset(deg, 0, sizeof deg);
m.clear();
}
void addedge(int u,int v){
e[cnt].to = v; deg[v]++;
e[cnt].next = head[u]; head[u] = cnt++;
}
string topsort(){
priority_queue<int,vector<int>,greater<int> > q;
for(int i = 1; i <= num; i++)
if(deg[i] == 0) {
q.push(i);
if(q.size()>1)
return "No";
}
if(q.size() == 1) return "Yes";
/*while(q.size()){
int u = q.top(); q.pop();
a[++len] = u;
for(int i = head[u]; ~i; i = e[i].next){
if(--deg[e[i].to] == 0)
q.push(e[i].to);
}
}
if(len < num) return "No";
else return "Yes";*/
return "No";
}
int main()
{
string p1,p2;
while(cin>>n, n){
init();
for(int i = 1;i <= n; i++){
cin>>p1>>p2;
if(m[p1] == 0) m[p1] = ++num;
if(m[p2] == 0) m[p2] = ++num;
addedge(m[p1],m[p2]);
//cout<<m[p1]<<' '<<m[p2]<<endl;
}
cout<<topsort()<<endl;
//for(int i = 1; i <= num; i++)
// cout<<a[i]<<' ';
}
return 0;
}