ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Link With Running || 杭电多校第四场T2 || Dijkstra + Tarjan + SPFA

2022-08-02 02:31:10  阅读:165  来源: 互联网

标签:杭电多校 Tarjan 第四场 int eg num edge ei ll


题面:http://acm.hdu.edu.cn/showproblem.php?pid=7175

题意:一个有向图,边权 ei 和 pi 。求从点 1 跑到点 n , 最小 Sum(ei) 是多少?在满足 Sum(ei) 最小的基础上,Sum(pi) 最大是多少?

ei 和 pi 大于等于 0。保证答案存在且可输出。

思路:

先用Dijkstra找最短路,然后再扫一遍找出最短路图。

由于e可为0,所以存在环。由于保证答案存在,所以不存在正环(否则没法找最长路。)即,存在且仅存在0环。

说白了就是逼着我们缩点。所以用Tarjan缩点。

然后缩完点后再建新图。新图为DAG。在该图上用SPFA找最长路(注意 Dijkstra没法找最长路。(一般情况))。由于该图为DAG,

所以可以使用入度优化大大提升效率。(否则会TLE)

代码:

  1 #include<bits/stdc++.h>
  2 #define ll long long
  3 #define min(a,b) ((a)<(b)?(a):(b))
  4 using namespace std;
  5 const int maxn=1e5+10,maxm=3e5+10;
  6 const ll inf=(ll)1e18+7;
  7 int T,n,m,edge_head[maxn],num_edge,num_eg,eg_head[maxn];
  8 ll dis[maxn];
  9 int dfn[maxn],low[maxn],col[maxn],num_col,st[maxn],ix,tp,din[maxn];
 10 queue<int>que;
 11 bool vis[maxn];
 12 struct Node{
 13     int id,eg;
 14     ll dis;
 15     bool operator <(const Node&a)const{
 16         return (a.dis<dis);
 17     }
 18 }nd;
 19 priority_queue<Node>q;
 20 struct Edge{
 21     int from,to,nx;
 22     ll e,p;
 23 }edge[maxm],eg[maxm];
 24 void Add_edge(int from,int to,ll e,ll p){
 25     edge[++num_edge].nx=edge_head[from];
 26     edge[num_edge].from=from;
 27     edge[num_edge].to=to;
 28     edge[num_edge].e=e;
 29     edge[num_edge].p=p;
 30     edge_head[from]=num_edge;
 31     return;
 32 }
 33 void Add_eg(int i){
 34     int from=edge[i].from,to=edge[i].to,p=edge[i].p;
 35     eg[++num_eg].nx=eg_head[from];
 36     eg[num_eg].from=from;
 37     eg[num_eg].to=to;
 38     eg[num_eg].p=p;
 39     eg_head[from]=num_eg;
 40     return;
 41 }
 42 void Dij(){
 43     while(!q.empty()) q.pop();
 44     nd.id=1;nd.dis=0;
 45     q.push(nd);
 46     dis[1]=0;
 47     for(int i=2;i<=n;i++) dis[i]=inf;
 48     while(!q.empty()){
 49         nd=q.top();
 50         q.pop();
 51         int u=nd.id;
 52         if(vis[u]){
 53             if(u==n) break;
 54             continue;
 55         }
 56         vis[u]=1;
 57         for(int i=edge_head[u];i;i=edge[i].nx){
 58             int v=edge[i].to;
 59             if(dis[u]+edge[i].e<dis[v]){
 60                 dis[v]=dis[u]+edge[i].e;
 61                 nd.id=v; nd.dis=dis[v];
 62                 nd.eg=i;
 63                 q.push(nd);
 64             }
 65         }
 66     }
 67 
 68     for(int u=1;u<=n;u++){
 69         if(dis[u]==inf) continue;
 70         for(int i=edge_head[u];i;i=edge[i].nx){
 71             int v=edge[i].to;
 72             if(dis[u]+edge[i].e==dis[v]) Add_eg(i);
 73         }
 74     }
 75     return;
 76 }
 77 void Tarjan(int x){
 78     st[++tp]=x;
 79     vis[x]=1;
 80     dfn[x]=low[x]=++ix;
 81     for(int i=eg_head[x];i;i=eg[i].nx){
 82         int y=eg[i].to;
 83         if(dfn[y]==0){
 84             Tarjan(y);
 85             low[x]=min(low[x],low[y]);
 86         }
 87         else if(vis[y]) low[x]=min(low[x],dfn[y]);
 88     }
 89     if(dfn[x]==low[x]){
 90         num_col++;
 91         do{
 92             vis[st[tp]]=0;
 93             col[st[tp]]=num_col;
 94             tp--;
 95         }while(st[tp+1]!=x);
 96     }
 97     return;
 98 }
 99 void Work(){
100     num_edge=0;
101     memset(edge_head,0,sizeof(edge_head));
102     for(int i=1;i<=num_eg;i++){
103         int u=eg[i].from,v=eg[i].to;
104         if(col[u]!=col[v])
105             Add_edge(col[u],col[v],0,eg[i].p),din[col[v]]++;
106     }
107     return;
108 }
109 void SPFA(){
110     que.push(col[1]);
111     dis[col[1]]=0;
112     while(!que.empty()){
113         int x=que.front();
114         que.pop();
115         for(int i=edge_head[x];i;i=edge[i].nx){
116             int y=edge[i].to;
117             if(dis[y]<dis[x]+edge[i].p)
118                 dis[y]=dis[x]+edge[i].p;
119             if(--din[y]==0) que.push(y);//DAG优化。
120         }
121     }
122     return;
123 }
124 int main(){
125     scanf("%d",&T);
126     while(T--){
127         num_edge=0;num_eg=0;
128         memset(edge_head,0,sizeof(edge_head));
129         memset(eg_head,0,sizeof(eg_head));
130         //init
131 
132         scanf("%d%d",&n,&m);
133         int a,b; ll c,d;
134         for(int i=1;i<=m;i++){
135             scanf("%d%d%lld%lld",&a,&b,&c,&d);
136             Add_edge(a,b,c,d);
137         }
138         //从1到n最短路dij
139         Dij();
140         printf("%lld ",dis[n]);
141         //init
142         num_col=0;
143         tp=ix=0;
144         memset(vis,0,sizeof(vis));
145         memset(dfn,0,sizeof(dfn));
146         memset(low,0,sizeof(low));
147         memset(st,0,sizeof(st));
148         //init
149         Tarjan(1);
150         //init
151         memset(din,0,sizeof(din));
152         memset(dis,0,sizeof(dis));
153         //init;
154         Work();
155         SPFA();
156         printf("%lld\n",dis[col[n]]);
157     }
158     return 0;
159 }
View Code

By: AlenaNuna

标签:杭电多校,Tarjan,第四场,int,eg,num,edge,ei,ll
来源: https://www.cnblogs.com/AlenaNuna/p/16542409.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有