XSY2278HDU5669the Red Sun(线段树+dijkstra)

Posted shuraeye

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了XSY2278HDU5669the Red Sun(线段树+dijkstra)相关的知识,希望对你有一定的参考价值。

\\(Description\\)

给定一张 \\(N\\) 个点的图, 点的标号为 \\(1\\)\\(n\\) . 我们进行 \\(M\\) 次连边, 每次连边可以描述为 \\(a\\) \\(b\\) \\(c\\) \\(d\\) \\(w:\\)

for i = a to b do

    for j = c to d do

         Add_Edge(i,j,w)        

\\(Add_Edge(i,j,w)\\) 表示从点 \\(i\\) 向点 \\(j\\) 连一条费用为 \\(w\\) 的双向边.

求点 \\(1\\) 到点 \\(n\\) 的最小花费.

为了降低难度, 我们有 \\(K\\) 次机会可以消除某条边的花费.


\\(Input\\)

第一行一个数 \\(T\\) , 表示测试数据组数. 出于某种原因, \\(T=1 .\\)

第二行三个数 \\(N,M,K\\) .

接下来 \\(M\\) 行, 每行 \\(5\\) 个数 \\(a,b,c,d,w\\) , 意义如题目描述所示.


\\(Output\\)

一行一个数, 为最小的花费.

如果点 \\(1\\) 与点 \\(n\\) 不连通, 输出 "Yww is our red sun!" .


\\(Sample Input\\)

1
5 3 0
1 2 4 5 42
5 5 4 4 468
1 1 3 3 335


\\(Sample Output\\)

42


\\(HINT\\)

\\(T=1,1≤N≤5×10^4,1≤M≤10^4,0≤K≤10,1≤w≤10^3\\)


\\(Source\\)

练习题 树4-1-线段树


思路

思路可以参考【XSY2434】【CF787D】遗产(也是我自己写的)

基本上思路一致

也是一个最短路的题目,使用线段树优化

对于每两个\\([a,b]\\)\\([c,d]\\)区间间的连边,我们设一个中间点\\(x\\),将\\([a,b]\\)连向\\(x\\),再由\\(x\\)连向\\([c,d]\\)

我们现在开始考虑怎么求最短路

我们都知道要使用\\(dijkstra\\)

但是多了一个限制条件我们有 \\(K\\) 次机会可以消除某条边的花费

于是我们显然想到了\\(dp\\)

\\(dis[i][j]\\)表示到达\\(i\\)节点,用了\\(j\\)次机会的最小花费

于是我们可以得到状转方程:

\\(\\begincasesdis[now.x][v]=now.cost+val[i]&dis[now.x][v]>now.cost+val[i]\\\\dis[now.x+1][v]=now.cost&now.x<k且dis[now.x+1][v]>now.cost\\endcases\\)

我们就可以快乐地实现最短路啦


代码

#include<bits/stdc++.h>
using namespace std;
const int N=400010,M=2000010;
int n,m,k,rt1,rt2,cnt=0;
int lc1[N],rc1[N],lc2[N],rc2[N];
int dis[15][N];
bool vis[15][N];
int w;
int to[M<<1],nxt[M<<1],val[M<<1],head[N];
int nodetot=0;
struct edge

    int u,cost,x;
    bool operator < (const edge & e)const
    
        return cost>e.cost;
    
;
void add(int u,int v,int wi)

    to[++cnt]=v;
    val[cnt]=wi;
    nxt[cnt]=head[u];
    head[u]=cnt;

int build1(int l,int r)

    if(l==r)return l;
    int now=++nodetot;
    int mid=(l+r)>>1;
    lc1[now-n]=build1(l,mid);
    add(lc1[now-n],now,0);
    rc1[now-n]=build1(mid+1,r);
    add(rc1[now-n],now,0);
    return now;

int build2(int l,int r)

    if(l==r)return l;
    int now=++nodetot;
    int mid=(l+r)>>1;
    lc2[now-n]=build2(l,mid);
    add(now,lc2[now-n],0);
    rc2[now-n]=build2(mid+1,r);
    add(now,rc2[now-n],0);
    return now;

void modify1(int k,int l,int r,int ql,int qr)

    if(ql<=l&&r<=qr)
    
        add(k,nodetot,w);
        return ;
    
    int mid=(l+r)>>1;
    if(ql<=mid)modify1(lc1[k-n],l,mid,ql,qr);
    if(qr>mid)modify1(rc1[k-n],mid+1,r,ql,qr);

void modify2(int k,int l,int r,int ql,int qr) 

    if(ql<=l&&r<=qr)
    
        add(nodetot,k,0);
        return ;    
    
    int mid=(l+r)>>1;
    if(ql<=mid)modify2(lc2[k-n],l,mid,ql,qr);
    if(qr>mid)modify2(rc2[k-n],mid+1,r,ql,qr);

priority_queue<edge>qu;
void dijkstra()

    memset(dis,127,sizeof(dis));
    dis[0][1]=0;
    qu.push((edge)1,0,0);
    edge now;
    while(!qu.empty())
    
        now=qu.top();
        qu.pop();
        if(vis[now.x][now.u])continue;
        vis[now.x][now.u]=1;
        for(int i=head[now.u];i;i=nxt[i])
        
            int v=to[i];
            if(dis[now.x][v]>now.cost+val[i]&&!vis[now.x][v])
            
                dis[now.x][v]=now.cost+val[i];
                qu.push((edge)v,dis[now.x][v],now.x);
            
            if(now.x<k&&!vis[now.x+1][v]&&dis[now.x+1][v]>now.cost)
            
                dis[now.x+1][v]=now.cost;
                qu.push((edge)v,dis[now.x+1][v],now.x+1);
            
        
    

int main()

    scanf("%d",&n);
    scanf("%d %d %d",&n,&m,&k);
    int a,b,c,d;
    nodetot=n;
    rt1=build1(1,n);
    rt2=build2(1,n);
    while(m--)
       
        scanf("%d %d %d %d %d",&a,&b,&c,&d,&w);
        nodetot++;//中间点
        modify1(rt1,1,n,a,b);modify2(rt2,1,n,c,d);
        nodetot++;//中间点
        modify1(rt1,1,n,c,d);modify2(rt2,1,n,a,b);
    
    dijkstra();
    int ans=dis[0][0];
    for(int i=0;i<=k;i++)ans=min(ans,dis[i][n]);
    if(ans==dis[0][0])puts("Yww is our red sun!");
    else printf("%d",ans);
    return 0; 
 

以上是关于XSY2278HDU5669the Red Sun(线段树+dijkstra)的主要内容,如果未能解决你的问题,请参考以下文章

HDU4822XSY2021Tri-war

XSY2538/HDU6155Subsequence Count(矩阵乘法+线段树)

xsy 2414CF587CDuff in the Army

XSY2414CF587CDuff in the Army(倍增lca)

[JZOJ 5669] Permutaition

记录片宇宙之the secret of the sun