bfs,dfs,图论
题意:给你n件任务,每个任务都有需要的时间,而且做该项任务当且仅当之前的一些任务完成,求最短时间。
思路:首先这些任务是分层的,有顺序之分,想到拓扑排序,然后我的思路是标记出每一层的起点和终点,每一层求出最大时间并累加,在实现的过程中发现标记不好打,看了题解的思路,有一点dp的味道,就是其实每项任务在同一层中是相互独立的,只与其前置任务的时间有关,然后ans是所有任务完成时间的最大值,
代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define maxn 10005
#define maxm 10000005
int ver[maxm],head[maxn],ne[maxm],endd[maxn],tim[maxn],in[maxn];
queue<int>st;
int tot=0;
void add(int x,int y){
ver[++tot]=y;ne[tot]=head[x];head[x]=tot;
}
int n;
void SCAN()
{
scanf("%d",&n);
int i;
for(i=1; i<=n; i++)
{
int a,c=1;
scanf("%d",&a);
scanf("%d",&tim[a]);
scanf("%d",&c);
while(c)
{
add(c,a);
scanf("%d",&c);
}
}
}
int main(){
memset(in,0,sizeof in);
SCAN();
int ans=0;
for(int i=0;i<10005;i++)if(in[i]==0)st.push(i);
while(!st.empty()){
int now=st.front();st.pop();endd[now]+=tim[now];
ans=max(ans,endd[now]);
for(int i=head[now];i;i=ne[i]){
int y=ver[i];
in[y]--;
endd[y]=max(endd[y],endd[now]);
if(in[y]==0)st.push(y);
}
}
cout<<ans<<endl;
return 0;}
2.spfa怎么死了
做洛谷最短路例题时候,有一道弱化数据版本和一道强化数据版本,这一看就是卡我们可爱的spfa的啊,
加强版用dijkstra过了,然鹅用spfa却死了,得了32分,ac了两个点t了4个。
其实我一直感觉dijkstra和spfa算法思路差不多,下面贴一下二者代码:
//dijkstra
#include<bits/stdc++.h>
#define ll long long
using namespace std;
#define maxn 100100
#define maxm 500010
ll inf=pow(2,31)-1;
ll d[maxn],head[maxn],ne[maxm],visited[maxn],ver[maxm],edge[maxm];
int tot=0;
priority_queue<pair<int,int> >q;
void add(int x,int y,int z){
ver[++tot]=y;edge[tot]=z;
ne[tot]=head[x];head[x]=tot;
}
void dijkstra(int p){
for(int i=0;i<maxn;i++)d[i]=inf;
memset(visited,0,sizeof visited);
d[p]=0;
q.push(make_pair(0,p));
while(q.size()){
int now=q.top().second;q.pop();
if(visited[now])continue;
visited[now]=1;
for(int i=head[now];i;i=ne[i]){
int y=ver[i],z=edge[i];
if(d[y]>d[now]+z){
d[y]=d[now]+z;
q.push(make_pair(-d[y],y));}
}
}
}
int main(){
int n,m,s;
cin>>n>>m>>s;
while(m--){
int x,y,z;
cin>>x>>y>>z;
add(x,y,z);
}
//cout<<inf<<endl;
dijkstra(s);
for(int i=1;i<=n;i++)cout<<d[i]<<' ';cout<<endl;
return 0;}
spfa
#include<bits/stdc++.h>
#define ll long long
#define maxn 100010
#define maxm 500010
using namespace std;
ll d[maxn],head[maxn],ne[maxm],visit[maxn],ver[maxm],edge[maxm];
int tot=0;
queue<int>q;
void add(int x,int y,int z){
ver[++tot]=y;edge[tot]=z;
ne[tot]=head[x];head[x]=tot;
}
void spfa(int s){
memset(d,0x3f,sizeof(d));
memset(visit,0,sizeof visit);
d[s]=0;visit[s]=1;
q.push(s);
while(q.size()){
int x=q.front();q.pop();
visit[x]=0;
for(int i=head[x];i;i=ne[i]){
int y=ver[i],z=edge[i];
if(d[y]>d[x]+z){
d[y]=d[x]+z;
if(!visit[y]){
q.push(y);visit[y]=1;
}
}
}
}
}
int main(){
int n,m,s;
cin>>n>>m>>s;
while(m--){
int x,y,z;
cin>>x>>y>>z;
add(x,y,z);
}
spfa(s);
for(int i=1;i<=n;i++)cout<<d[i]<<' ';
return 0;}
二者最大区别是dijkstra是对点操作,spfa是对边操作(队列优化的bellman-ford)
蓝书上是这样写的:在任意时刻,该算法的队列都保存了待拓展的节点,每次入队相当于完成一次dist数组的更新操作,十七满足三角形不等式。一个节点可能会入队,出队多次,最终,图中节点收
敛到全部满足三角形不等式的状态。这个队列避免了bellman-Ford算法中对不需要拓展的节点的冗余
扫描,在随机图上运行效率为o(km)(k为小常数),但在随机构造(特意设计)的图上,该算法很可能退化为o(nm),必须谨慎使用
所以,哪些图可以卡掉我们可爱的spfa呢?
本文作者:misasteria
本文链接:https://www.cnblogs.com/misasteria/p/16027219.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步