Skip to content

泉州一中信息学Blog

信息学奥赛技术分享博客

  • 登录
  • 小学oj
  • 中学oj
  • 测试页面1
  • Toggle search form

长乐一中 Day 2 2023/7/16

Posted on 2023年7月16日2023年7月17日 By KMP 长乐一中 Day 2 2023/7/16无评论

最短路径

啥也不会。

鞭尸一下qjk

所以今天早上没有打比赛然后去改题了,因为T1乘法逆元忘了咋写,T2想了半天想不出来最后发现又要用什么什么不认识的算法,T3那个鬼畜方法谁能想出来啊。

T1

link

这道题需要用到最短路的部分特别简单,毕竟很显然的是只需要求出每个关键点到每个点的最短路即可,一个点开始燃烧的时间即所有关键点到它的最短路的最小值。

如果时间不会被推迟,那么对于每个点都有一条最短路小于图完全燃烧的时间。

以上都很显然。

接下来根据ybtoj的题解需要用到一些我看不懂的数学方法,根据baidu的结果需要用到dp,我都不会。

T2

link

斯坦纳树题。

根据OIwiki的搜索结果,是一种很神奇的树。由于它在洛谷的模板题有紫,我感觉我是打不出这题了。

(安详地瘫倒

T3

link

正反建图,分别求出原点和汇点为1的单源最短路和单汇最短路(这个谁都会)。分别记录单源最短路与单汇最短路中每个点u的最短路中距离1最近的节点为p[u]和rp[u]。

枚举图中每条边,分情况更新答案。

写这个blog的时候改这题改了一半,后面还有点小问题没搞懂,我明天早上早点来机房吧。

upd 2023/7/17 7: 39:

改出来了。

枚举图中每条边,分情况更新答案:

当u=1时,显然没必要更新,因为这种情况会被其他情况覆盖

当v=1时,如果p[u]=u,这种情况不合法(1-u-1),要经过其他边,而经过其他边的情况也会被其他情况覆盖;若p[u]!=u,则用d[u]+w更新答案(很显然,不解释)

当u!=1且v!=1时,如果p[u]=rp[v],会出现重复经过的点,不合法;如果p[u]!=rp[v],就用d[u]+rd[v]+w更新答案(也很显然)。

code:

#include<bits/stdc++.h>
using namespace std;
const int N=1e4+10,M=4e5+10;
int n,m,h[2][N],nxt[2][M],to[2][M],w[2][M],cnt[2]={-1,-1};
int dis[2][N],p[2][N];
bool vis[N];
struct node{
    int dis,id;
    bool operator < (const node cmx)const{
        return dis>cmx.dis;
    }
};
void add(int x,int y,int v,int i){
    nxt[i][++cnt[i]]=h[i][x];
    h[i][x]=cnt[i];
    to[i][cnt[i]]=y;
    w[i][cnt[i]]=v;
    return;
}
void dijkstra(int i){
    memset(vis,false,sizeof vis);
    priority_queue<node> q;
    dis[i][1]=0;
    q.push((node){0,1});
    while (!q.empty()){
        int u=q.top().id;
        q.pop();
        if (vis[u]){
            continue;
        }
        vis[u]=true;
        for (int j=h[i][u];~j;j=nxt[i][j]){
            int v=to[i][j];
            if (dis[i][v]>dis[i][u]+w[i][j]){
                dis[i][v]=dis[i][u]+w[i][j];
                q.push((node){dis[i][v],v});
                if (u==1){
                    p[i][v]=v;
                }
                else{
                    p[i][v]=p[i][u];
                }
            }
        }
    }
    return;
}
int main()
{
    freopen("circle.in","r",stdin);
    freopen("circle.out","w",stdout);
    memset(dis,0x3f3f3f3f,sizeof dis);
    memset(h,-1,sizeof h);
    scanf("%d%d",&n,&m);
    for (int i=1;i<=m;i++){
        int s,t,w1,w2;
        scanf("%d%d%d%d",&s,&t,&w1,&w2);
        add(s,t,w1,0);
        add(t,s,w2,0);
        add(s,t,w2,1);
        add(t,s,w1,1);
    }
    dijkstra(0);
    dijkstra(1);
    int ans=0x3f3f3f3f;
    for (int u=2;u<=n;u++){
        for (int i=h[0][u];~i;i=nxt[0][i]){
            int v=to[0][i];
            if (v==1){
                if (p[0][u]!=u){
                    ans=min(ans,dis[0][u]+w[0][i]);
                }
            }
            else{
                if (p[0][u]!=p[1][v]){
                    ans=min(ans,dis[0][u]+dis[1][v]+w[0][i]);
                }
            }
        }
    }
    printf("%d",ans);
    return 0;
}

强连通分量

T1

link

考试的时候基本想出正解,却忘了最长链三个字了。于是没打出来。看完题解之后迅速搞了一下。

易证明ans即为缩点后最长链长度(缩点后每个点点权是其强连通分量中的点数)。

code:

#include
using namespace std;
const int N=1e6+10;
int n,m,h[N],to[N],nxt[N],cnt=-1;
int dfn[N],low[N],col[N],k,Time;
int hh[N],too[N],nxtt[N],cntt=-1,q[N];
stack st;
int dis[N],inn[N];
queue que;
void add(int x,int y){
    nxt[++cnt]=h[x];
    h[x]=cnt;
    to[cnt]=y;
    return;
}
void addd(int x,int y){
    nxtt[++cntt]=hh[x];
    hh[x]=cntt;
    too[cntt]=y;
    return;
}
void dfs(int u){
    dfn[u]=low[u]=++Time;
    st.push(u);
    for (int i=h[u];~i;i=nxt[i]){
        int v=to[i];
        if (!dfn[v]){
            dfs(v);
            low[u]=min(low[u],low[v]);
        }
        else if (!col[v]){
            low[u]=min(low[u],low[v]);
        }
    }
    if (low[u]==dfn[u]){
        col[u]=++k;
        while (st.top()!=u){
            col[st.top()]=col[u];
            st.pop();
        }
        st.pop();
    }
    return;
}
int main()
{
    freopen("bomb.in","r",stdin);
    freopen("bomb.out","w",stdout);
    memset(h,-1,sizeof h);
    memset(hh,-1,sizeof hh);
    scanf("%d%d",&n,&m);
    for (int i=1;i<=m;i++){
        int u,v;
        scanf("%d%d",&u,&v);
        add(u,v);
    }
    for (int i=1;i<=n;i++){
        if (!dfn[i]){
            dfs(i);
        }
    }
    for (int i=1;i<=n;i++){
        for (int j=h[i];~j;j=nxt[j]){
            int v=to[j];
            if (col[i]==col[v]){
                continue;
            }
            addd(col[i],col[v]);
            inn[col[v]]++;
        }
    }
    for (int i=1;i<=n;i++){
        q[col[i]]++;
    }
    for (int i=1;i<=k;i++){
        if (!inn[i]){
            que.push(i);
            dis[i]=q[i];
        }
    }
    while (!que.empty()){
        int u=que.front();
        que.pop();
        for (int i=hh[u];~i;i=nxtt[i]){
            int v=too[i];
            inn[v]--;
            dis[v]=max(dis[v],dis[u]+q[v]);
            if (!inn[v]){
                que.push(v);
            }
        }
    }
    int ans=0;
    for (int i=1;i<=k;i++){
        ans=max(ans,dis[i]);
    }
    printf("%d",ans);
    return 0;
}

T2

link

几乎是板题,不解释。但是考试的时候也是忘了最长链三个字,于是考场上写了一个近似于SPFA的bfs。

回头看完题解之后一看自己的代码,这不就是一个SPFA吗。于是稍加修改就过了。

code:

#include
using namespace std;
const int N=5e5+10;
int n,m,h[N],to[N],nxt[N],cnt=-1,q[N],p,s;
int dfn[N],low[N],col[N],k,Time;
stack st;
bool j[N],vis[N];
int hh[N],too[N],nxtt[N],cntt=-1,qq[N],jj[N];
int ans[N];
queue que;
void add(int x,int y){
    nxt[++cnt]=h[x];
    h[x]=cnt;
    to[cnt]=y;
    return;
}
void addd(int x,int y){
    nxtt[++cntt]=hh[x];
    hh[x]=cntt;
    too[cntt]=y;
    return;
}
void dfs(int u){
    dfn[u]=low[u]=++Time;
    st.push(u);
    for (int i=h[u];~i;i=nxt[i]){
        int v=to[i];
        if (!dfn[v]){
            dfs(v);
            low[u]=min(low[u],low[v]);
        }
        else if (!col[v]){
            low[u]=min(low[u],low[v]);
        }
    }
    if (low[u]==dfn[u]){
        col[u]=++k;
        while (st.top()!=u){
            col[st.top()]=col[u];
            st.pop();
        }
        st.pop();
    }
    return;
}
int main()
{
    freopen("plan.in","r",stdin);
    freopen("plan.out","w",stdout);
    memset(h,-1,sizeof h);
    memset(hh,-1,sizeof hh);
    scanf("%d%d",&n,&m);
    for (int i=1;i<=m;i++){
        int u,v;
        scanf("%d%d",&u,&v);
        add(u,v);
    }
    for (int i=1;i<=n;i++){
        scanf("%d",&q[i]);
    }
    scanf("%d%d",&s,&p);
    for (int i=1;i<=p;i++){
        int x;
        scanf("%d",&x);
        j[x]=true;
    }
    for (int i=1;i<=n;i++){
        if (!dfn[i]){
            dfs(i);
        }
    }
    s=col[s];
    for (int i=1;i<=n;i++){
        for (int j=h[i];~j;j=nxt[j]){
            int v=to[j];
            if (col[i]==col[v]){
                continue;
            }
            addd(col[i],col[v]);
        }
    }
    for (int i=1;i<=n;i++){
        qq[col[i]]+=q[i];
        if (j[i]){
            jj[col[i]]=true;
        }
    }
    que.push(s);
    ans[s]=qq[s];
    while (!que.empty()){
        int u=que.front();
        que.pop();
        for (int i=hh[u];~i;i=nxtt[i]){
            int v=too[i];
            if (ans[v]<ans[u]+qq[v]){
                ans[v]=ans[u]+qq[v];
                if (!vis[v]){
                    que.push(v);
                    vis[v]=true;
                }
            }
        }
        vis[u]=false;
    }
    int cmx=0;
    for (int i=1;i<=k;i++){
        if (jj[i]){
            cmx=max(cmx,ans[i]);
        }
    }
    printf("%d",cmx);
    return 0;
}

T3

不会打2-SAT,我待会再看看QAQ。

训练日志

文章导航

Previous Post: 长了集训Day7
Next Post: 常乐集训2

发表回复 取消回复

要发表评论,您必须先登录。

2025年 6月
一 二 三 四 五 六 日
 1
2345678
9101112131415
16171819202122
23242526272829
30  
« 2月    

2024常州 Class Classic OI Problems Contest cqr的长乐集训2023 CZYZ LOC New Game NOI NOIP Password Protected PM_PK Preview Problems Retrospect Selfmade Qusetion STL The end Training Uneasy Problem 蒟蒻 通报

  • 训练日志
  • 链表
  • 入门
  • 模拟
  • dfs序
  • 并查集
  • spfa
  • 最小割
  • 矩阵树定理
  • 仙人掌
  • BSGS
  • 凸包
  • 回文自动机
  • 递推与动归
  • 堆
  • 莫队算法
  • ST表
  • Treap
  • 树套树
  • 可持久化线段树
  • 初赛
  • 搜索
  • 贪心
  • 深度优先搜索
  • 欧拉图
  • dijkstra
  • 费用流
  • 哈夫曼树
  • kruskual
  • 置换
  • 旋转卡壳
  • KMP
  • 区间动归
  • STL
  • 链表
  • 可并堆
  • sply
  • 主席树
  • 可持久化字典树
  • 算法
  • 动态规划
  • 构造
  • 广度优先搜索
  • 最短路
  • floyd
  • 最大流
  • 虚树
  • prim
  • 筛法
  • 半平面交
  • 字典树
  • 背包动归
  • 基础数据结构
  • 分块
  • 线段树
  • 替罪羊树
  • K-DTree
  • 图论
  • 二分法
  • 迭代搜索
  • 拓扑排序
  • 有上下界网络流
  • 生成树
  • 快速幂
  • 后缀数组
  • 树形动归
  • 哈希表
  • 中级数据结构
  • 平衡树
  • 可持久化数据结构
  • 数据结构
  • 三分法
  • 启发式搜索
  • 图的连通
  • 点分治
  • 博弈论
  • AC自动机
  • 状压动归
  • 单调栈
  • 树状数组
  • 高级数据结构
  • OI资料
  • 数学
  • 高精度
  • 差分约束
  • 树上倍增
  • 素数测试
  • 后缀自动机
  • 数位动归
  • 单调队列
  • 新闻
  • 几何
  • 随机化
  • 二分图染色
  • 树链剖分
  • 欧拉函数
  • manacher
  • 斜率优化
  • 离线处理
  • 信息学奥赛学长风采
  • 字符串
  • 二分图匹配
  • prufer编码
  • 卡特兰数
  • 密码学
  • 决策单调
  • 赛后总结
  • 其他
  • 2-SAT
  • 最近公共祖先
  • 矩阵乘法
  • 记忆化搜索
  • 网络流
  • Link cut tree
  • 排列组合
  • 树
  • 高斯消元
  • 乘法逆元
  • 容斥原理
  • 调和级数
  • 概率与期望
  • 模线性方程组
  • 莫比乌斯反演
  • 快速傅里叶变换
  • 扩展欧几里德
  • 最大公约数与最小公倍数

近期文章

  • DP杂题
  • 2025年2月13日模拟赛
  • HLOJ-TEST ROUND 4-T1/T2(构造)- 3
  • HLOJ-TEST ROUND 4-T1/T2(构造)- 2
  • HLOJ-TEST ROUND 4-T1/T2(构造)- 1

近期评论

归档

  • 2025年2月
  • 2025年1月
  • 2024年11月
  • 2024年10月
  • 2024年9月
  • 2024年8月
  • 2024年7月
  • 2024年3月
  • 2024年2月
  • 2024年1月
  • 2023年12月
  • 2023年11月
  • 2023年10月
  • 2023年9月
  • 2023年8月
  • 2023年7月
  • 2023年3月
  • 2023年2月
  • 2023年1月
  • 2022年12月

Copyright © 2025 泉州一中信息学Blog.

Powered by PressBook WordPress theme