2 条题解
-
0

// 差分约束 SPFA 算法 O(NM) #include<bits/stdc++.h> using namespace std; const int N=50005,M=N*3; int h[N],to[M],ww[M],ne[M],idx; void add(int a,int b,int c){ to[++idx]=b,ww[idx]=c,ne[idx]=h[a],h[a]=idx; } int n,d[N]; bool vis[N]; void spfa(){ memset(d,-0x3f,sizeof d); d[0]=0; queue<int> q; q.push(0); vis[0]=true; while(!q.empty()){ int u=q.front(); q.pop(); vis[u]=false; for(int i=h[u]; i; i=ne[i]){ int v=to[i]; if(d[v]<d[u]+ww[i]){ //最长路 d[v]=d[u]+ww[i]; if(!vis[v]) q.push(v),vis[v]=true; } } } } int main(){ scanf("%d",&n); idx=0; memset(h,0,sizeof h); for(int i=1; i<N; i++){ add(i-1,i,0); //i-(i-1)>=0 add(i,i-1,-1); //(i-1)-i>=-1 } for(int i=1,a,b,c; i<=n; i++){ scanf("%d%d%d",&a,&b,&c); a++,b++; add(a-1,b,c); //b-(a-1)>=c } spfa(); printf("%d\n",d[50001]); } -
0
求最少点,所以求最长路,建边形式要求:
G[a].push_back({b,c})#include <bits/stdc++.h> using namespace std; const int N=5e4+10; vector<pair<int,int>>G[N]; int n,d[N]; bool v[N]; int spfa() { memset(d,-0x3f,sizeof(d)); memset(v,0,sizeof(v)); // 初始距离为负无穷,标记数组初始为未访问 queue<int>q;q.push(0);d[0]=0;v[0]=1; // 起点0,距离0,标记为访问 while(!q.empty()) { int x=q.front();q.pop();v[x]=0; // 出队,标记为未访问 for(auto i:G[x]) // 遍历x的邻接边 { int y=i.first, c=i.second; // 终点y,边权c if(d[y]<d[x]+c) // 如果y的距离可以被更新 { d[y]=d[x]+c; // 更新距离 if(!v[y]) q.push(y),v[y]=1; // 若未访问,入队并标记 } } } return d[n]; // 返回终点n的距离 } int main() { int m; scanf("%d", &m); // 读入边数m for(int i=1,x,y,c;i<=m;i++) // 读入m条边 { scanf("%d%d%d",&x,&y,&c); x++;y++; // 点编号+1(可能原输入从1开始) G[x-1].push_back({y, c}); // 从x-1到y连边,权值c(满足xa+c <= xb) } n=50001; // 总点数n=50001 for(int i=0;i<n;i++) // 添加点之间顺序约束的边 { G[i+1].push_back({i,-1}); // 从i+1到i连边,权值-1(d[i+1] <= d[i]+1) G[i].push_back({i+1, 0}); // 从i到i+1连边,权值0(d[i] <= d[i+1]) } printf("%d\n",spfa()); // 输出结果 return 0; }
- 1
信息
- ID
- 1449
- 时间
- 1000ms
- 内存
- 128MiB
- 难度
- 7
- 标签
- 递交数
- 167
- 已通过
- 38
- 上传者