当前位置:网站首页>【杭电多校第四场 B题】最短路图+缩点dp
【杭电多校第四场 B题】最短路图+缩点dp
2022-08-01 07:37:00 【宇智波一打七~】
题目链接
题目描述:
题意:
题意就是给你一个有向图,每条边有两个权值,问第一个权值的最短路是多少,而且在第一个权值最小的情况下第二个权值之和的最大值是多少
分析:
很容易想到的就是跑一个最短路然后建一个最短路图再跑一个最长路,因为可能有环,所以跑一个spfa就直接出来,好多人都是这么想的,但是这样想是不对的,因为有环的话跑最长路一定是有问题的,所以说咱们可以用tarjan算法把这个有向图给缩成DAG,然后dp就行,dp[i]代表从1号点所在的连通块到i号联通块的第二个权值之和的最大值,下面请看代码:
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 200010,M = 300010;
int h[N],e[M+M],w[M+M],p[M+M],ne[M+M],idx;
int h1[N],e1[M+M],w1[M+M],p1[M+M],ne1[M+M],idx1;
inline void add(int a,int b,int c,int d) {
e[idx] = b;
w[idx] = c;
p[idx] = d;
ne[idx] = h[a];
h[a] = idx++;
}
inline void add1(int a,int b,int c,int d) {
e1[idx1] = b;
w1[idx1] = c;
p1[idx1] = d;
ne1[idx1] = h1[a];
h1[a] = idx1++;
}
inline int read() {
int f=1,x=0;
char c=getchar();
while(c<'0'||c>'9') {
if(c=='-') f=-1;
c=getchar();
}
while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
return f*x;
}
int n,m;
int dfn[N],low[N],bel[N],tt,cnt,ww[N];
bool ins[N];
stack<int> stk;
vector<vector<int> > scc;
bool st[N];
int dis[N];
int dijkstra(int start,int end) {
for(int i=1; i<=n; i++) dis[i] = 0x3f3f3f3f3f3f3f3f,st[i] = false;
dis[start] = 0;
priority_queue<pair<int,int>,vector<pair<int,int> >,greater<pair<int,int> > > q;
q.push(make_pair(0,start));
while(q.size()) {
int t = q.top().second;
q.pop();
if(st[t]) continue;
st[t] = true;
for(int i=h[t]; i!=-1; i=ne[i]) {
int j = e[i];
if(dis[j] > dis[t] + w[i]) {
dis[j] = dis[t] + w[i];
q.push(make_pair(dis[j],j));
}
}
}
}
void dfs(int u) {
dfn[u] = low[u] = ++tt;
stk.push(u);
ins[u] = true;
for(int i=h1[u]; i!=-1; i=ne1[i]) {
int v = e1[i];
if(!dfn[v]) dfs(v);
if(ins[v]) low[u] = min(low[u],low[v]);
}
if(low[u] == dfn[u]) {
++cnt;
while(true) {
int v = stk.top();
stk.pop();
ins[v] = false;
bel[v] = cnt;
if(u == v) break;
}
}
}
int deg[N],f[N];
void topo(){
queue<int> q;
for(int i=1;i<=cnt;i++) if(!deg[i]) q.push(i);
while(!q.empty()){
int t = q.front();
q.pop();
for(int i=h[t];i!=-1;i=ne[i]){
int j = e[i];
deg[j]--;
f[j] = max(f[j],f[t]+p[i]);
if(!deg[j]) q.push(j);
}
}
}
void solve() {
n = read(),m = read();
idx1 = cnt = idx = tt = 0;
for(int i=1; i<=n; i++) h[i] = h1[i] = -1,ins[i] = f[i] = ww[i] = dfn[i] = low[i] = bel[i] = deg[i] = 0;
while(!stk.empty()) stk.pop();
while(m--) {
int u = read(),v = read(),e = read(),p = read();
add(u,v,e,p);
}
dijkstra(1,n);
printf("%lld ",dis[n]);
for(int i=1;i<=n;i++){
for(int k=h[i];k!=-1;k=ne[k]){
int j = e[k];
if(dis[j] == dis[i] + w[k]) add1(i,j,w[k],p[k]);
}
}
for(int i=1;i<=n;i++) h[i] = -1;idx = 0;
for(int i=1; i<=n; i++) if(!dfn[i]) dfs(i);
for(int i=1; i<=n; i++) {
for(int k=h1[i]; k!=-1; k=ne1[k]) {
int j = e1[k];
if(bel[i] != bel[j]) add(bel[i],bel[j],w1[k],p1[k]),deg[bel[j]]++;
}
}
topo();
printf("%lld\n",f[bel[n]]);
}
signed main() {
int _=read();
while(_--) solve();
return 0;
}
/* 2 3 3 1 2 1 1 2 3 1 1 1 3 2 0 */
边栏推荐
- pytest接口自动化测试框架 | parametrize中ids的用法
- 零代码网站开发利器:WordPress
- 华为深度学习课程第六、七章
- LabVIEW RT中的用户界面更新速度
- 【MySQL】操作表DML相关语句
- 爆肝3万字,最硬核丨Mysql 知识体系、命令全集 【建议收藏 】
- 微信小程序请求封装
- 2022杭电多校第二场1011 DOS Card(线段树)
- 图片无损压缩软件哪个好用:试试完全免费的JPG-C 图片批量修整压缩减肥工具吧 | 最新jpg批量修整工具下载
- 【ASWC Arxml结构分解】-7-Explicit(显式)和Implicit(隐式) Sender-Receiver communication描述差异
猜你喜欢
随机推荐
pytest接口自动化测试框架 | 执行失败跳转pdb
套接字选项
2022杭电多校第二场1011 DOS Card(线段树)
最小生成树
Zero-code website development tool: WordPress
NIO programming
The log causes these pits in the thread block, you have to prevent
GO错误处理方式
MATLAB program design and application of MATLAB 2.5
MySQL row locks and gap locks
GO error handling
rhcsa 第三次
Data organization -- singly linked list of the linear table
Summary of test points about app updates in different ways
POJ1287联网题解
Guest brush SQL - 2
Electromagnetic compatibility introductory tutorial (6) test project
VSCode插件推荐(Rust环境)
三维坐标系距离
centos 安装php7.4,搭建hyperf,转发RDS