之前做过一道dp+拓扑的题,用到了邻接表+队列的拓扑,
后来忘写博客了(大概好久以前了),今天补上
因为拓扑排序的答案是不唯一的,所以我们可以把所有入度为0的点都先放到队列里面,然后对于队列中的每一个点找它存储在邻接表里相邻的其它点,使其入度减一,经过这样的操作可以达到O(n+e)的复杂度。
当题目中要求特定输出顺序的时候,比如优先输出节点小的,我们就可以把队列改为优先队列来达到要求。
如果要判断环,可以用一个cnt统计入队列的点的个数,如果cnt<n(点的个数),那么就有环.
代码如下:
vector<int>v[MAXL+50];
int num[MAXL+50];
int n,m;
int ans[MAXL+50];
void toposort()
{
priority_queue<int,vector<int>,greater<int> >q;//当要求编号小的优先输出时用优先队列存储点
for(int i=1;i<=n;i++)
if(!num[i])
q.push(i);
int len=0;
while(!q.empty())
{
int u=q.top();
q.pop();
ans[len++]=u;
for(int i=0;i<v[u].size();i++)
{
int t=v[u][i];
num[t]--;
if(!num[t])
q.push(t);
}
}
cout<<ans[0];
for(int i=1;i<len;i++)
cout<<" "<<ans[i];
cout<<endl;
}
int main()
{
while(cin>>n>>m)
{
memset(num,0);
for(int i=1;i<=m;i++)
{
int x,y;
cin>>x>>y;
num[y]++;
v[x].push_back(y);
}
toposort();
for(int i=0;i<=n;i++)
v[i].clear();
}
}
例题:HDU 1285
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<vector>
#include<queue>
#define eps 1e-8
#define memset(a,v) memset(a,v,sizeof(a))
using namespace std;
typedef long long int LL;
const int MAXL(1e5);
const int INF(0x7f7f7f7f);
const int mod(1e9+7);
int dir[4][2]= {{-1,0},{1,0},{0,1},{0,-1}};
vector<int>v[MAXL+50];
int num[MAXL+50];
int n,m;
int ans[MAXL+50];
void toposort()
{
priority_queue<int,vector<int>,greater<int> >q;
for(int i=1;i<=n;i++)
if(!num[i])
q.push(i);
int len=0;
while(!q.empty())
{
int u=q.top();
q.pop();
ans[len++]=u;
for(int i=0;i<v[u].size();i++)
{
int t=v[u][i];
num[t]--;
if(!num[t])
q.push(t);
}
}
cout<<ans[0];
for(int i=1;i<len;i++)
cout<<" "<<ans[i];
cout<<endl;
}
int main()
{
while(cin>>n>>m)
{
memset(num,0);
for(int i=1;i<=m;i++)
{
int x,y;
cin>>x>>y;
num[y]++;
v[x].push_back(y);
}
toposort();
for(int i=0;i<=n;i++)
v[i].clear();
}
}