20250405周赛-S
链接
A. 日历
我的:
#include<bits/stdc++.h>
using namespace std;
int n,d[105],ans;
bool check(int x,int y){
if(x<10){
if(y<10){
return x==y;
}
else{
return x==y%10&&x==y/10;
}
}
else{
if(y<10){
return y==x%10&&y==x/10;
}
else{
return y/10==x/10&&y%10==x%10&&y%10==y/10;
}
}
}
int main(){
cin>>n;
for(int i=1;i<=n;i++){
scanf("%d",&d[i]);
}
for(int i=1;i<=n;i++){
for(int j=1;j<=d[i];j++){
if(check(i,j))ans++;
}
}
cout<<ans;
return 0;
}
短的:
#include <bits/stdc++.h>
using namespace std;
int ans = 0, n, d, t;
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
scanf("%d", &d);
if (i > 9 && i % 11)
continue;
t = i % 10;
if (d >= t)
ans += 1 + (d >= t * 11);
}
cout << ans;
return 0;
}
B. 埃尔德什数
我的bfs:
#include <bits/stdc++.h>
using namespace std;
int n, m, x, vis[100005], visid[100005], dist[100005];
vector<int> a[100005], id[100005];
queue<int> q;
int main() {
cin >> n >> m;
for (int i = 1; i <= m; i++) {
int k;
scanf("%d", &k);
for (int j = 1; j <= k; j++) {
scanf("%d", &x);
a[i].push_back(x);
id[x].push_back(i);
}
}
memset(dist, 0x3f, sizeof(dist));
q.push(1);
vis[1] = 1;
dist[1] = 0;
while (q.size()) {
int x = q.front();
q.pop();
for (auto y : id[x]) {
if (visid[y])
continue;
for (auto z : a[y]) {
if (!vis[z]) {
dist[z] = dist[x] + 1;
q.push(z);
vis[z] = 1;
}
}
visid[y] = 1;
}
}
for (int i = 1; i <= n; i++) {
if (dist[i] == 0x3f3f3f3f)
printf("-1\n");
else
printf("%d\n", dist[i]);
}
return 0;
}
正解:
建虚边虚点(一组一组),答案除二
#include <bits/stdc++.h>
using namespace std;
int n,m,k,v;
vector<int> g[200005];
int main() {
cin>>n>>m;
for(int i=0;i<m;i++){
cin>>k;
for(int j=0;j<k;j++){
cin>>v;
g[--v].push_back(n+i);
g[n+i].push_back(v);
}
}
queue<int> q;
q.push(0);
vector<int> dist(n+m,-2);
dist[0]=0;
while(!q.empty()){
int u=q.front();q.pop();
for (int i:g[u])
if(dist[i]+2) ;
else dist[i]=dist[u]+1,q.push(i);
}
for(int i=0;i<n;i++) cout<<dist[i]/2<<'\n';
}
C. 方格连通性
bfs,没得说
我的:
#include<bits/stdc++.h>
using namespace std;
int n,m,q,mp[2005][2005],fa[4000006];
int dx[]={0,0,1,-1};
int dy[]={1,-1,0,0};
int fd(int x){
if(fa[x]==x)return x;
return fa[x]=fd(fa[x]);
}
void merge(int x,int y){
int fx=fd(x),fy=fd(y);
fa[fx]=fy;
}
int main(){
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
fa[(i-1)*m+j]=(i-1)*m+j;
}
}
cin>>q;
for(int i=1;i<=q;i++){
int op;scanf("%d",&op);
if(op==1){
int a,b;
scanf("%d%d",&a,&b);
mp[a][b]=1;
for(int u=0;u<4;u++){
int nx=a+dx[u],ny=b+dy[u];
if(mp[nx][ny]){
if(fd((a-1)*m+b)!=fd((nx-1)*m+ny))merge((a-1)*m+b,(nx-1)*m+ny);
}
}
}
else{
int a,b,c,d;
scanf("%d%d%d%d",&a,&b,&c,&d);
if(fd((a-1)*m+b)==fd((c-1)*m+d)&&mp[a][b]){
printf("Yes\n");
}
else{
printf("No\n");
}
}
}
return 0;
}
D. 别样的旅行
水过:O(n^3logn)
#include<bits/stdc++.h>
using namespace std;
int n,m,a[505][505],b[505][505],dist[505][505],vis[505][505];
struct S{
short x,y;
int a;
};
bool operator<(S a,S b){
return a.a>b.a;
}
priority_queue<S>q;
int main(){
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
cin>>n>>m;
for(int i=1;i<=n;i++){
for(int j=1;j<m;j++){
scanf("%d",&a[i][j]);
}
}
for(int i=1;i<n;i++){
for(int j=1;j<=m;j++){
scanf("%d",&b[i][j]);
}
}
memset(dist,0x3f,sizeof(dist));
dist[1][1]=0;
q.push({1,1,0});
S x;
while(!q.empty()){
x=q.top();q.pop();
if(vis[x.x][x.y])continue;
if(x.x==n&&x.y==m)break;
vis[x.x][x.y]=1;
if(x.y!=m){
if(dist[x.x][x.y+1]>dist[x.x][x.y]+a[x.x][x.y]){
dist[x.x][x.y+1]=dist[x.x][x.y]+a[x.x][x.y];
q.push({x.x,x.y+1,dist[x.x][x.y+1]});
}
}
if(x.y!=1){
if(dist[x.x][x.y-1]>dist[x.x][x.y]+a[x.x][x.y-1]){
dist[x.x][x.y-1]=dist[x.x][x.y]+a[x.x][x.y-1];
q.push({x.x,x.y-1,dist[x.x][x.y-1]});
}
}
if(x.x!=n){
if(dist[x.x+1][x.y]>dist[x.x][x.y]+b[x.x][x.y]){
dist[x.x+1][x.y]=dist[x.x][x.y]+b[x.x][x.y];
q.push({x.x+1,x.y,dist[x.x+1][x.y]});
}
}
for(int i=1;i<x.x;i++){
if(dist[x.x-i][x.y]>dist[x.x][x.y]+i+1){
dist[x.x-i][x.y]=dist[x.x][x.y]+i+1;
q.push({x.x-i,x.y,dist[x.x-i][x.y]});
}
}
}
printf("%d",dist[n][m]);
return 0;
}
正解:少一个O(n^2logn)
最难受的是这个
如果花费是i那么就是到(r-1,c)代价1
那么i+1,即需要记录上一次是不是向上走的,若是代价1,若不是代价2
#include<bits/stdc++.h>
using namespace std;
int n,m,a[505][505],b[505][505],dist[505][505][2],vis[505][505][2];
struct S{
int x,y,f;
int a;
};
bool operator<(S a,S b){
return a.a>b.a;
}
priority_queue<S>q;
int main(){
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
cin>>n>>m;
for(int i=1;i<=n;i++){
for(int j=1;j<m;j++){
scanf("%d",&a[i][j]);
}
}
for(int i=1;i<n;i++){
for(int j=1;j<=m;j++){
scanf("%d",&b[i][j]);
}
}
memset(dist,0x3f,sizeof(dist));
dist[1][1][0]=0;
q.push({1,1,0,0});
S x;
while(!q.empty()){
x=q.top();q.pop();
if(vis[x.x][x.y][x.f])continue;
if(x.x==n&&x.y==m)break;
vis[x.x][x.y][x.f]=1;
if(x.y!=m){
if(dist[x.x][x.y+1][0]>dist[x.x][x.y][x.f]+a[x.x][x.y]){
dist[x.x][x.y+1][0]=dist[x.x][x.y][x.f]+a[x.x][x.y];
q.push({x.x,x.y+1,0,dist[x.x][x.y+1][0]});
}
}
if(x.y!=1){
if(dist[x.x][x.y-1][0]>dist[x.x][x.y][x.f]+a[x.x][x.y-1]){
dist[x.x][x.y-1][0]=dist[x.x][x.y][x.f]+a[x.x][x.y-1];
q.push({x.x,x.y-1,0,dist[x.x][x.y-1][0]});
}
}
if(x.x!=n){
if(dist[x.x+1][x.y][0]>dist[x.x][x.y][x.f]+b[x.x][x.y]){
dist[x.x+1][x.y][0]=dist[x.x][x.y][x.f]+b[x.x][x.y];
q.push({x.x+1,x.y,0,dist[x.x+1][x.y][0]});
}
}
if(x.x!=1){
if(dist[x.x-1][x.y][1]>dist[x.x][x.y][x.f]+2-x.f){
dist[x.x-1][x.y][1]=dist[x.x][x.y][x.f]+2-x.f;
q.push({x.x-1,x.y,1,dist[x.x-1][x.y][1]});
}
}
}
printf("%d",min(dist[n][m][0],dist[n][m][1]));
return 0;
}
E. 逆向边
对于nan:判断是否在同一个连通块即可
对于inf:即存在正环,若有负环反着走就是正环,所以只要有非零环即可
其他的那就是两点距离,和树的处理方法相同
#include<bits/stdc++.h>
using namespace std;
const long long N=1e5+5;
long long n,m,q,idx,vis[N],dist[N],huan[N];
long long head[N],nxt[N*2],v[N*2],e[N*2],tot;
void add(long long a,long long b,long long c){
nxt[++tot]=head[a];
v[tot]=b,e[tot]=c;
head[a]=tot;
}
void dfs(long long x){
vis[x]=idx;
for(long long i=head[x];i;i=nxt[i]){
long long y=v[i],z=e[i];
if(vis[y]){
if(dist[y]!=dist[x]+z)huan[idx]=1;//非零环
continue;
}
vis[y]=1;dist[y]=dist[x]+z;
dfs(y);
}
}
int main(){
cin>>n>>m>>q;
for(long long i=1;i<=m;i++){
long long a,b,c;
scanf("%lld%lld%lld",&a,&b,&c);
add(a,b,c);
add(b,a,-c);
}
for(long long i=1;i<=n;i++){
if(!vis[i]){
idx++;
dfs(i);
}
}//连通块划分
for(long long i=1;i<=q;i++){
long long x,y;scanf("%lld%lld",&x,&y);
if(vis[y]!=vis[x])printf("nan\n");
else if(huan[vis[x]])printf("inf\n");
else printf("%lld\n",dist[y]-dist[x]);//注意距离
}
return 0;
}