拓扑排序
做了一些拓扑排序题目来做个总结 怕忘 (老年人记性不好)
1.拓扑排序理论理解
拓扑排序是一种图的运用问题,主要针对的是AOV图,也就是活动步骤这方面的问题解决,特点就是 一步接着一步,做完这一步才能到下一步,不能越界
对应图论来说,重点就是 对于一个结点它的入度是否为0,为0的时候表示这件事情之前的事情已经全部做完,可以开始做这件事了。
当然做完一件事情也要 完全消去这件事 确保其他事能够接着做,(图中只要删除伸出去的边,并减少所连接点的入度即可)
拓扑排序常用解决排名问题,任务安排问题等 一件件事情一个个解决而事于事之间有联系 的问题(还有其他神奇的用途)
2.拓扑排序的板子
拓扑排序哪来的板子
写法方面有一定的规律
建图: (习惯用链式前向星) 我也有博客讲解哦~ 链式前向星图存储优化
struct dd{
ll e,pr;
}d[N];
ll last[N];
ll cnt=0;
void add(ll f,ll e) //反向建图
{
d[++cnt].e=e;
d[cnt].pr=last[f];
last[f]=cnt;
}
ll n,m;
int main()
{
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
cin >> n >> m;
ll f,e;
vector<ll> in(n+5); //入度
while(m--)
{
cin >> f >> e;
add(f,e);in[e]++; //记录入度
}
其他建图也可以,重点在要记录入度值
常用操作:
queue<ll> q; //常用队列保存入度为0的数并进行下一步操作
for(ri i=1;i<=n;i++)
if(!in[i]) q.push(i);
ll tp,to;
while(!q.empty())
{
tp=q.top();q.pop();cout << tp << '\n';
for(ri i=last[tp];i;i=d[i].pr)
{
to=d[i].e;
// 特殊操作...
if(!(--in[to])) //去边
q.push(to);
}
}
这些步骤就可以灵活自己变化了,队列可以用优先队列来进行不同要求的改变,特殊操作也可以根据实际情况修改
3.入门题
洛谷拓扑排序题单
洛谷P4017最大食物链
洛谷P2712摄像头
洛谷P1960郁闷的记者
特殊:
HDU1285确定比赛名次
由于排序特殊要求要用到最小堆,也就是优先队列
队列变成:
priority_queue<int,vector<int>,greater<int> >q; //最小堆
保证小的数比大的数先输出(题目要求)