WY模拟赛10

WY模拟赛10

T1. 洛谷 P9431 [NAPC-#1] Stage3 - Jump RefreshersPairs S

原题

依据关系建立点与点之间的图上关系,然后对于可以相互到达的点,也就是强连通分量进行缩点,然后跑最长路即可。

能跑最长路的是SPFA,不是dijkstra。 当然这里用SPFA应该会 $ T $ 。

code:

#include <bits/stdc++.h> 
#define i8  __int128
#define int long long 
#define fuck inline
#define lb long double 
using namespace std; 
// typedef long long ll; 
const int N=3e3+5,M=9e6+5,mod=536870912;
const int INF=1e9+7; 
const int inf=LONG_LONG_MAX/4;
// const int mod1=469762049,mod2=998244353,mod3=1004535809;
// const int G=3,Gi=332748118; 
// const int M=mod1*mod2;
fuck int read()
{
    int x=0,f=1;
    char c=getchar();
    while(c<'0'||c>'9'){if(c=='-'){f=-1;}c=getchar();}
    while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+(c-'0');c=getchar();}
    return x*f;
}
fuck void write(int x)
{
    if(x<0){putchar('-');x=-x;}
    if(x>9) write(x/10);
    putchar(x%10+'0');
}
struct node{int x,y,id;}a[N];
vector<int>g[N];
int vis[N],c[N],type=0,sum[N];
stack<int>st;
int dep=0,dfn[N],low[N];
fuck void tj(int u)
{
    dfn[u]=low[u]=++dep;
    vis[u]=1;st.push(u);
    for(auto v:g[u])
    {
        if(!dfn[v])
        {
            tj(v);
            low[u]=min(low[u],low[v]);
        }
        else if(vis[v])low[u]=min(low[u],dfn[v]);
    }
    if(dfn[u]==low[u])
    {
        ++type;
        while(st.top()!=u)
        {
            c[st.top()]=type;
            vis[st.top()]=0;
            sum[type]++;
            st.pop();
        }
        c[u]=type;
        vis[u]=0;
        sum[type]++;
        st.pop();
    }
}
int n,d,s,cost[N],vis2[N];
vector<pair<int,int> >G[N];
fuck void dfs(int u,int cs)
{
    vis2[u]=1;
    cost[u]=max(cost[u],cs);
    for(auto v:G[u])
    {
        if(vis2[v.first]||cost[v.first]>=cs+v.second)continue;//等于号不能少
        dfs(v.first,cs+v.second);
    }
    vis2[u]=0;
}
fuck void clr()
{
    for(int i=1;i<=n;i++)
    {
        vis2[i]=0;
        cost[i]=0;
        dfn[i]=0;
        low[i]=0;
        vis[i]=0;
        sum[i]=0;
        c[i]=0;
        g[i].clear();
        G[i].clear();
    }
    type=0;dep=0;
}
fuck void solve()
{
    n=read(),d=read(),s=read();
    clr();
    for(int i=1;i<=n;i++)a[i].x=read(),a[i].y=read(),a[i].id=i;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
        {
            if(i==j)continue;
            if(abs(a[j].x-a[i].x)<=a[j].y-a[i].y+d)
            {
                g[j].push_back(i);
            }
        }
    // for(int i=1;i<=n;i++)
    // {
    //     for(auto v:g[i])cout<<v<<" ";
    //     cout<<endl;
    // }
    // for(int i=1;i<=n;i++){if(!dfn[i])tj(i);}
    tj(s);
    int sta=c[s];
    // for(int i=1;i<=n;i++)cout<<c[i]<<" ";
    // cout<<"\n";
    // cout<<type<<"\n";
    int ans=sum[sta];
    for(int i=1;i<=type;i++)
    {
        for(int j=1;j<=n;j++)
        {
            if(c[j]==i)
            {
                for(auto v:g[j])
                {
                    if(c[v]==i)continue;
                    G[i].push_back({c[v],sum[c[v]]});
                }
            }
        }
    }
    // for(int i=1;i<=type;i++)
    // {
    //     for(auto v:G[i])cout<<v.first<<" ";
    //     cout<<endl;
    // }
    dfs(sta,0);
    int frz=0;
    // for(int i=1;i<=type;i++)cout<<cost[i]<<" ";
    // cout<<endl;
    for(int i=1;i<=type;i++)frz=max(frz,cost[i]);
    cout<<ans+frz<<"\n";
}
signed main() 
{ 
    // ios::sync_with_stdio(false); 
    // cin.tie(0); cout.tie(0); 
    int QwQ=read();
    int fuckccf=read();
    while(QwQ--)solve(); 
    // solve(); 
    return 0; 
}
//  6666   66666  666666 
// 6    6  6   6      6 
// 6    6  6666      6 
// 6    6  6  6    6 
//  6666   6   6  6666666

T2. 洛谷 P11022 「LAOI-6」Yet Another Graph Coloration Problem

原题

构造:

  1. 将节点 $ x $ 以及以及它在 $ DFS $ 树中的所有子孙节点(即 $ x $ 的子树)全部染成黑色。
  2. 将图中的其余所有节点染成白色。

无解:

  1. 图不连通。
  2. 图是一棵树。

附带一组数据:

1
6 6
1 2
2 3
3 1
1 4
2 5
3 6
#include <bits/stdc++.h> 
#define i8  __int128
// #define int long long 
#define fuck inline
#define lb long double 
using namespace std; 
typedef long long ll; 
const int N=2e6+5,M=64,mod=536870912;
const int INF=1e9+7; 
const ll inf=LONG_LONG_MAX/4;
// const int mod1=469762049,mod2=998244353,mod3=1004535809;
// const int G=3,Gi=332748118; 
// const int M=mod1*mod2;
fuck int read()
{
    int x=0,f=1;
    char c=getchar();
    while(c<'0'||c>'9'){if(c=='-'){f=-1;}c=getchar();}
    while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+(c-'0');c=getchar();}
    return x*f;
}
fuck void write(int x)
{
    if(x<0){putchar('-');x=-x;}
    if(x>9) write(x/10);
    putchar(x%10+'0');
}
vector<int>g[N];
int vis[N];
int frz[N];
int ans;
fuck void dfs(int u,int fa)
{
    vis[u]=1;
    for(auto v:g[u])
    {
        if(v==fa)continue;
        if(vis[v])
        {
            if(ans==0)ans=1,frz[u]=1;
        }
        else dfs(v,u);
    }
}
fuck void dfs2(int x,int fa)
{
    vis[x]=1;
    frz[x]=max(frz[x],fa);
    for(auto v:g[x])
    {
        if(!vis[v])dfs2(v,max(fa,frz[x]));
    }
}
int n,m;
fuck void clr()
{
    for(int i=1;i<=n;i++)
    {
        g[i].clear();
        vis[i]=0;
        frz[i]=0;
    }
    ans=0;
}
fuck void solve()
{
    n=read(),m=read();
    clr();
    for(int i=1;i<=m;i++)
    {
        int u,v;u=read(),v=read();
        g[u].push_back(v);
        g[v].push_back(u);
    }
    dfs(1,0);
    for(int i=1;i<=n;i++)
    {
        if(vis[i]==0)
        {
            cout<<-1<<"\n";
            return;
        }
    }
    if(ans==0)
    {
        cout<<-1<<"\n";
        return;
    }
    for(int i=1;i<=n;i++)vis[i]=0;
    dfs2(1,0);
    for(int i=1;i<=n;i++)
    {
        if(frz[i])cout<<"B";
        else cout<<"W";
    }
    cout<<"\n";
}
signed main() 
{ 
    // ios::sync_with_stdio(false); 
    // cin.tie(0); cout.tie(0); 
    int QwQ=read();
    // int fuckccf=read();
    while(QwQ--)solve(); 
    // solve(); 
    return 0; 
}
//  6666   66666  666666 
// 6    6  6   6      6 
// 6    6  6666      6 
// 6    6  6  6    6 
//  6666   6   6  6666666

T3. 洛谷 B4309 [蓝桥杯青少年组国赛 2024] 第四题

原题

分讨一下:

  1. 初始就有两个以上的连通分量,答案为 $ 0 $ ;
  2. 总数少于 $ 3 $ 个,在不满足条件1的前提下,答案为 $ -1 $ ;
  3. 图存在割点,答案为 $ 1 $ ;
  4. 图不存在割点,答案为 $ 2 $ ;
#include <bits/stdc++.h> 
#define i8  __int128
// #define int long long 
#define fuck inline
#define lb long double 
using namespace std; 
typedef long long ll; 
const int N=3e6+5,M=64,mod=536870912;
const int INF=1e9+7; 
const ll inf=LONG_LONG_MAX/4;
// const int mod1=469762049,mod2=998244353,mod3=1004535809;
// const int G=3,Gi=332748118; 
// const int M=mod1*mod2;
fuck int read()
{
    int x=0,f=1;
    char c=getchar();
    while(c<'0'||c>'9'){if(c=='-'){f=-1;}c=getchar();}
    while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+(c-'0');c=getchar();}
    return x*f;
}
fuck void write(int x)
{
    if(x<0){putchar('-');x=-x;}
    if(x>9) write(x/10);
    putchar(x%10+'0');
}
int dfn[N],low[N],vis[N];
int ans[N];
vector<int>g[N];
fuck void tj(int u,int op)
{
    low[u]=dfn[u];
    int cnt=0;vis[u]=1;
    for(auto v:g[u])
    {
        if(!dfn[v])
        {
            dfn[v]=dfn[u]+1;
            tj(v,0);
            low[u]=min(low[u],low[v]);
            // cout<<u<<" "<<low[v]<<" "<<dfn[u]<<endl;
            cnt+=(low[v]>=dfn[u]?1:0);
        }
        else if(vis[v])low[u]=min(low[u],dfn[v]);
    }
    // cout<<u<<" "<<op<<" "<<cnt<<endl;
    if(op==1&&cnt>=2)ans[u]=1;
    if(op==0&&cnt>=1)ans[u]=1;
}
int n,m;
fuck int getid(int x,int y){return (x-1)*m+y;}
char a[105][105];
fuck void clr()
{
    memset(vis,0,sizeof(vis));
    memset(dfn,0,sizeof(dfn));
    memset(ans,0,sizeof(ans));
    for(int i=0;i<N-10;i++)g[i].clear();
    memset(low,0,sizeof(low));
}
int dx[10]={1,-1,0,0};
int dy[10]={0,0,-1,1};
fuck void solve()
{
    clr();
    int cnt2=0;
    cin>>n>>m;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
        {
            cin>>a[i][j];
            if(a[i][j]=='G')cnt2++;
        }
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            for(int k=0;k<4;k++)
            {
                int x=i+dx[k],y=j+dy[k];
                if(!x||!y||x>n||y>m||a[x][y]!='G'||a[i][j]!='G')continue;
                g[getid(i,j)].push_back(getid(x,y));//g[getid(x,y)].push_back(getid(i,j));
            }
    
    
    int cnt1=0;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
        {
            if(!dfn[getid(i,j)]&&a[i][j]=='G')dfn[getid(i,j)]=1,tj(getid(i,j),1),cnt1++;
        }
    if(cnt1>=2){cout<<0<<"\n";return;}
    if(cnt2<3){cout<<-1<<"\n";return;}
    int sum=0;
    for(int i=1;i<=n*m;i++)sum+=ans[i];
    if(sum>0)cout<<1<<"\n";
    else cout<<2<<"\n";
}
signed main() 
{ 
    // ios::sync_with_stdio(false); 
    // cin.tie(0); cout.tie(0); 
    int QwQ=read();
    // int fuckccf=read();
    while(QwQ--)solve(); 
    // solve(); 
    return 0; 
}
//  6666   66666  666666 
// 6    6  6   6      6 
// 6    6  6666      6 
// 6    6  6  6    6 
//  6666   6   6  6666666

T4. 洛谷 P8269 [USACO22OPEN] Visits S

原题

根据拜访关系建图完后发现是一个内向的森林,对于树枝上的必定能拜访到,直接加,对于环上的选择最小的边不加即可。

code:

#include <bits/stdc++.h> 
#define i8  __int128
#define int long long 
#define fuck inline
#define lb long double 
using namespace std; 
// typedef long long ll; 
const int N=2e5+5,M=64,mod=998244353;
const int inf=INT_MAX,INF=1e9+7; 
// const int mod1=469762049,mod2=998244353,mod3=1004535809;
// const int G=3,Gi=332748118; 
// const int M=mod1*mod2;
fuck int read()
{
    int x=0,f=1;
    char c=getchar();
    while(c<'0'||c>'9'){if(c=='-'){f=-1;}c=getchar();}
    while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+(c-'0');c=getchar();}
    return x*f;
}
fuck void write(int x)
{
    if(x<0){putchar('-');x=-x;}
    if(x>9) write(x/10);
    putchar(x%10+'0');
}
int n,ans=0;
int vis[N],val[N],ind[N];
int g[N];
fuck void topo()
{
    queue<int>q;
    for(int i=1;i<=n;i++)if(!ind[i])q.push(i);
    while(!q.empty())
    {
        int u=q.front();q.pop();
        vis[u]=1;
        ans+=val[u];
        int v=g[u];
        ind[v]--;
        if(!ind[v])q.push(v);
    }
}
int len=inf;
fuck void dfs(int u,int fa)
{
    vis[u]=1;
    len=min(len,val[u]);
    int v=g[u];
    if(!vis[v])dfs(v,u);
}
fuck void solve()
{
    cin>>n;
    // cout<<"aaaaaaaaaaaaaaaaaaaaaaaa"<<"\n";
    for(int i=1;i<=n;i++)
    {
        int a,v;cin>>a>>v;
        g[i]=a;
        val[i]=v;ind[a]++;
    }
    // cout<<"bbbbbbbbbbbbbbbbbbbbbbb"<<"\n";
    topo();
    // cout<<"cccccccccccccccccccccc"<<"\n";
    for(int i=1;i<=n;i++)
    {
        if(!vis[i])ans+=val[i];
    }
    // cout<<"ddddddddddddddddddd"<<"\n";
    // cout<<ans<<endl;
    for(int i=1;i<=n;i++)
    {
        if(!vis[i])
        {
            len=inf;
            dfs(i,0);
            ans-=len;
        }
    }
    // cout<<"eeeeeeeeeeeeeeee"<<endl;
    cout<<ans<<endl;
}
signed main() 
{ 
    // ios::sync_with_stdio(false); 
    // cin.tie(0); cout.tie(0); 
    // int fuckccf=read();
    // int QwQ=read();
    // while(QwQ--)solve(); 
    solve(); 
    return 0; 
}
//  6666   66666  666666 
// 6    6  6   6      6 
// 6    6  6666      6 
// 6    6  6  6    6 
//  6666   6   6  6666666





总结

  1. 需要提高代码实现速度;
  2. 精确计算数组大小;
  3. 积累更多的建图经验。

完结收工!!!!!

个人主页

看完点赞,养成习惯

\(\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\)

posted @ 2025-07-16 07:58  Nightmares_oi  阅读(11)  评论(0)    收藏  举报