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
构造:
- 将节点 $ x $ 以及以及它在 $ DFS $ 树中的所有子孙节点(即 $ x $ 的子树)全部染成黑色。
- 将图中的其余所有节点染成白色。
无解:
- 图不连通。
- 图是一棵树。
附带一组数据:
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] 第四题
分讨一下:
- 初始就有两个以上的连通分量,答案为 $ 0 $ ;
- 总数少于 $ 3 $ 个,在不满足条件1的前提下,答案为 $ -1 $ ;
- 图存在割点,答案为 $ 1 $ ;
- 图不存在割点,答案为 $ 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
总结
- 需要提高代码实现速度;
- 精确计算数组大小;
- 积累更多的建图经验。
完结收工!!!!!

看完点赞,养成习惯
\(\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\)

浙公网安备 33010602011771号