P1807 最长路
思路
题目描述
设 G 为有 n 个顶点的带权有向无环图,G 中各顶点的编号为 1 到 n,请设计算法,计算图 G 中 <1,n> 间的最长路径。
有向无环图 这个条件可以告诉我们可以使用 拓扑排序
(当然可以用单源最短路径相关算法)
细节
- 一个变量sum,记录遍历过的所有点的总数,总数小于n继续遍历
- 用栈来实现递归时,注意栈内有多少个数,栈内没有数就不用继续遍历
- 因为是求1到n的各点距离,所以先要从1点开始遍历
代码
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
int n,m;
const int maxn=1e4+10;
const int maxm=5e5+10;
struct node{
int v,next,w;
}e[maxm];
int r[maxn];
int head[maxm];
int cnt=0;
int top=0;
int dis[maxn];
int ans[maxn];
void add(int u,int v,int w){
e[++cnt].v=v;
e[cnt].w=w;
e[cnt].next=head[u];
head[u]=cnt;
}
int main(){
memset(head,0,sizeof(head));
memset(r,0,sizeof(r));
cin>>n>>m;
for(int i=1;i<=n;++i) dis[i]=-1e5-10;
for(int i=1;i<=m;++i){
int u,v,w;
cin>>u>>v>>w;
add(u,v,w);
r[v]++;
}
int top=0,sum=0;
for(int i=n;i>=1;--i)
if(r[i]==0)
ans[++top]=i;
dis[1]=0;
while(sum<n && top>0){
int s=ans[top--];++sum;
for(int i=head[s];i;i=e[i].next){
int v=e[i].v;
int w=e[i].w;
r[v]--;
if(dis[v]<dis[s]+w) dis[v]=dis[s]+w;
if(r[v]==0)
ans[++top]=v;
}
}
if(dis[n]!=-1e5-10)
cout<<dis[n]<<endl;
else cout<<"-1"<<endl;
return 0;
}
推荐题目
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
int n,m;
const int maxn=1e5+10;
const int maxm=2e5+10;
int head[maxm];
int cnt=0;
struct node{
int v,next;
}e[maxm*3];
void add(int u,int v){
e[++cnt].v=v;
e[cnt].next=head[u];
head[u]=cnt;
}
int st[maxn];
int top=0;
int r[maxn];
int ans[maxn];
int main(){
cin>>n>>m;
memset(head,0,sizeof(head));
memset(ans,0,sizeof(ans));
for(int i=1;i<=m;++i){
int x,y;
cin>>x>>y;
add(x,y);
r[y]++;
}
for(int i=n;i>=1;--i) if(r[i]==0) st[++top]=i,ans[i]=1;
int sum=0;
ans[1]=1;
while(top>0 && sum<n){
int s=st[top--];
++sum;
for(int i=head[s];i;i=e[i].next){
int v=e[i].v;
r[v]--;
if(ans[v]<ans[s]+1) ans[v]=ans[s]+1;
if(r[v]==0 ) st[++top]=v;
}
}
for(int i=1;i<=n;++i)
cout<<ans[i]<<endl;
return 0;
}