省选模拟3.22

$T1$

考场上分析出了几个性质,觉得是个贪心$/DP$结果从贪心耽误太久了,$dp$没有细想

还是说$dp[i]$表示前$i$个子图的满足情况的最小价值

怎么说,考场上想到的那个贪心就是这个,然后我对于区间操作就卡了,好吧,我还是稍逊一些

还是说,我们转移的时候,先看一下,我们这一段的右端点在哪

那么就可以分块转移了

其实只有两种转移吧,一个是后面直接连前面,或者目前点直接连最远点

目前点到最远点之间会存在断点使得使得两边断掉,那么还是一个个转移就好了

在思考一下

其实本质过程是分段,$n^3$的话很好说

我们考虑优化掉一维$dp[i]$表示前$i$个分成若干段代价的最小值,考虑$i->j$

那么就很好说了

首先我们对于这一部分,我们现在是$l$,我们对于我们目前可达右端点,必然是枚举当前是否为断点去判断

我们往后更新的话,需要更新一下连边情况,如果当前点,没有被打标记,其余的区间赋值,没有连边的都连上就好了,或者更新下一步能不能断点就好了,挺神的

#include<cstring>
#include<vector>
#include<cstdio>
using namespace std;
int n,m,in1,in2,dp[200010];
vector<int>ed[200010];bool vis[200010];
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d",&in1,&in2);
        ed[min(in1,in2)].push_back(max(in1,in2));
    }
    memset(dp,0x3f,sizeof(dp));
    dp[1]=0;
    for(int l=1,r=1,cn=0;l<=n;l++)
    {
        if(!vis[l])cn++;
        for(vector<int>::iterator ite=ed[l].begin();ite!=ed[l].end();ite++)
        {
             r=max(r,*ite);
             if(!vis[*ite])
                cn++,vis[*ite]=true;
        }
        r=max(r,l+1);
        dp[r]=min(dp[r],dp[l]+r-cn);
        if(l!=1)dp[l+1]=min(dp[l+1],dp[l]+1);
    }
    printf("%d",dp[n]);return 0;
}

 

$T2$

考场上想到了前两步,$1,2$起手,然后不会往后延伸了

只有$HH$和我一样...

那么以示尊敬,$1,2$起手

然后对于后面来说,我们对于目前点都能到的点都连$100$

最优解的话,我们保证都有一条向上的$1$

跑出来的是这样走$1->2->3->5/1->4->6$

最优解的话可以$1->2->4->5->8->9/1->3->6->7$

就是隔一个跨三个,然后一个连后面

大概就是走一步走三步这样就好了

$T3$

上午最短路写成大根堆了$QAQ$

//没处理向下的
//用脑子想一想
//出现问题的只有前面一部分,如果那么只需要H和dis取个max就好了
//其实也就是,前面的dis如果不大于H,证明前面这部分还有剩余
//其实就是看这个影响的部分,首先我们不需考虑往上的代价,只需要考虑往下和前进的代价的代价
//如果我们前面的距离不足到的话,我们就需要取个max
//dis的两种更新方式罢了 
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f3f3f3f3f
#define int long long
#define MAXN 6000005
using namespace std;
int head[MAXN],nxt[MAXN],val[MAXN],dis[MAXN],to[MAXN],h[MAXN],tot,H,n,m;
priority_queue<pair<int,int>,vector<pair<int,int> >,greater<pair<int,int> > >q;
bool vis[MAXN];
void add(int u,int v,int w)
{
     tot++;
     to[tot]=v;
     val[tot]=w;
     nxt[tot]=head[u];
     head[u]=tot;    
}
void dij()
{
     memset(dis,0x3f,sizeof(dis));
     dis[1]=0;
     q.push(make_pair(dis[1],1));
     while(!q.empty())
     {
             int now=q.top().second;
             q.pop();
             if(vis[now]) continue;
             vis[now]=true;
             for(int i=head[now];i;i=nxt[i])
             {
                 int y=to[i];
                int w=dis[now]+val[i];
                if(H>h[y]) w=max(w,H-h[y]);
                if(dis[y]>w)
                {
                   dis[y]=w;
                   q.push(make_pair(dis[y],y));
                }
              }
     }
     if(dis[n]==INF)
     {
         puts("-1");
         exit(0);
     }
     cout<<2*dis[n]-H+h[n];
}
int u,v,w;
signed main()
{
    cin>>n>>m>>H;
    for(int i=1;i<=n;i++)
    {
        cin>>h[i];
    }
    for(int i=1;i<=m;i++)
    {
        cin>>u>>v>>w;
        if(h[u]>=w) add(u,v,w);
        if(h[v]>=w) add(v,u,w);
    }
    dij();
} 

 

posted @ 2022-03-22 17:26  Authentic_k  阅读(18)  评论(0编辑  收藏  举报