ICode9

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

[PA2012]Tax 题解

2021-11-04 19:33:41  阅读:209  来源: 互联网

标签:... head ch int 题解 PA2012 Tax out dis


Statement

[PA2012]Tax - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

Solution

dijkstra+最短路建模

题目的难点显然在于说怎么处理这个最大值的问题

嗯...先把一条双向边拆成两条有向边...权值在边不好搞,考虑边转点?...这个最大值有点像带悔贪心...

对于一个点,我们把与它有关的边分为入边和出边

(上图中 \(in,out\) 是对应的,因为原图是无向图)

先对边转成的点按照边权排序

考虑到最大值这个带悔贪心类似的东西,我们可以想到像这样连边

其中 \(\Delta w\) 表示的是两条边边权差。

这样连边之后,我们从 \(in_1\) 这边过来就有了选择的余地,比如想从 \(out_2\) 出去,会得到正确贡献

当我们从 \(in_2\) 过来的时候,因为取 \(max\) ,所以 \((out_2,out_1)\) 边权 \(0\) ,很妙

最后一个问题在于处理起点和终点,

非常好办,建立超级源点 \(s\) 和超级汇点 \(t\) , 然后所有从 \(1\) 出发的边,从 \(s\) 向这些边转成的点连原图权值的边

同样,所有结束于 \(n\) 的边,从这些边转的点向 \(t\) 连原图权值的边

跑一边 \(dijkstra\) 即可,这样连边,点数是 \(O(m)\) 的,边数是 \(O(m)\) 的,复杂度 \(O(m\log m)\)

Code

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 2e5+5;

int read(){
    int s=0,w=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9')s=s*10+ch-'0',ch=getchar();
    return s*w;
}

struct Edge{
    int nex,to;
    int dis;
}edge[N<<3];
struct Line{
    int v,w,id;
    Line(int v,int w,int id):v(v),w(w),id(id){}
    bool operator<(const Line&rhs)const{return w<rhs.w;}
};
struct node{
    int v,w;
    node(int v,int w):v(v),w(w){}
    bool operator<(const node&rhs)const{return w>rhs.w;}
};
priority_queue<node>q;
vector<Line>Edge[N];
int head[N<<2];
int dis[N<<2];
int n,m,elen=1,s=0,t=1;
bool vis[N<<2];

bool chkmin(int &a,int b){return a>b?a=b,1:0;}
void addedge(int u,int v,int w){edge[++elen]={head[u],v,w},head[u]=elen;}
void dijkstra(){
    memset(dis,0x3f,sizeof(dis));
    q.push(node(s,dis[s]=0));
    while(q.size()){
        int u=q.top().v; q.pop();
        if(vis[u])continue; vis[u]=1;
        for(int e=head[u],v;v=edge[e].to,~e;e=edge[e].nex)
            if(chkmin(dis[v],dis[u]+edge[e].dis))q.push(node(v,dis[v]));
    }
}

signed main(){
    memset(head,-1,sizeof(head));
    n=read(),m=read();
    for(int i=1,u,v,w;i<=m;++i)
        u=read(),v=read(),w=read(),
        Edge[u].push_back(Line(v,w,i<<1)),
        Edge[v].push_back(Line(u,w,i<<1|1)),
        addedge(i<<1,i<<1|1,w),addedge(i<<1|1,i<<1,w);
    for(int i=1;i<=n;++i){
        sort(Edge[i].begin(),Edge[i].end());
        for(auto v:Edge[i]){
            if(i==1)addedge(s,v.id,v.w);
            if(v.v==n)addedge(v.id,t,v.w);
        }
        for(int j=1;j<(int)Edge[i].size();++j)
            addedge(Edge[i][j].id,Edge[i][j-1].id,0),
            addedge(Edge[i][j-1].id,Edge[i][j].id,Edge[i][j].w-Edge[i][j-1].w);
    }
    dijkstra();
    printf("%lld\n",dis[t]);
    return 0;
}

标签:...,head,ch,int,题解,PA2012,Tax,out,dis
来源: https://www.cnblogs.com/wyb-sen/p/15509865.html

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

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

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

ICode9版权所有