国庆day2考试总结--下午

· · 个人记录

前言

芭比Q了

problem A

模板题,但是我没有写对,原因是我没有判断<C和判断-1时条件出错

problem.A 正确代码

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=2e6+5;
struct node
{
    int x,y,w;
}e[N];
bool cmp(node e,node b)
{
    return e.w<b.w;
}
int fa[N],x[N],y[N];
int find(int x)
{
    if(fa[x]==x)return x;
    return fa[x]=find(fa[x]);
}
void unionn(int x,int y)
{
    x=find(x),y=find(y);
    if(x==y)return ;
    fa[x]=y; 
}
int n,k,cnt;
void kruskal()
{
    sort(e+1,e+1+cnt,cmp);
    int ans=0,sum=0;
    for(int i=1;i<=cnt;i++)
    {
        if(find(e[i].x)==find(e[i].y))continue;
        unionn(e[i].x,e[i].y);
        ans++;
        sum+=e[i].w;
    }
    if(ans<n-1)cout<<"-1"; 
    else cout<<sum;
}
signed main()
{
    cin>>n>>k;
    for(int i=1;i<=n;i++)fa[i]=i;
    for(int i=1;i<=n;i++)
    {
        cin>>x[i]>>y[i];
        int nx=x[i],ny=y[i];
        for(int j=1;j<i;j++)
        {
            int zx=x[j],zy=y[j];
            int ans=(nx-zx)*(nx-zx)+(ny-zy)*(ny-zy);
            if(ans>=k)
            {
                cnt++;
                e[cnt].x=i;
                e[cnt].y=j;
                e[cnt].w=ans;
            }
        }
    }
    kruskal();
    return 0;
 }

problem B

依旧模板题,但是我忘记在kruskal函数里面把e[i].x和e[i].y合并了

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e6+5;
int fa[N],x[N],y[N],n;
struct node
{
    int x,y,w;
}e[N];
bool cmp(node a,node b)
{
    return a.w<b.w;
}
int find(int x)
{
    if(fa[x]==x)return fa[x];
    return fa[x]=find(fa[x]);
}
void unionn(int x,int y)
{
    x=find(x),y=find(y);
    if(x==y)return ;
    fa[x]=y;
    return ;
}
int cnt;
void kruskal()
{
    sort(e+1,e+1+cnt,cmp);
    int ans=0,sum=0;
    for(int i=1;i<=cnt;i++)
    {
        int x=find(e[i].x),y=find(e[i].y);
        if(x==y)continue;
        ans++;
        unionn(e[i].x,e[i].y);
        sum=e[i].w; 
    }
    cout<<sum;
    return ;
}
signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0),cout.tie(0);
    cin>>n;
    for(int i=1;i<=n;i++)fa[i]=i;
    for(int i=1;i<=n;i++)cin>>x[i]>>y[i];
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        { 
            if(i==j)continue;
            cnt++;
            e[cnt].x=i;
            e[cnt].y=j;
            e[cnt].w=(x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]);
        }
    }
    kruskal();
    return 0;
}

problem C

主要是数组原因,然后就是vector push和size求错(下次肯定用数组),再加上输出是<号少写了一个导致CE,其他都想得一摸一样

problem C 正确代码

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=4e6+5,M=2005;
int fa[M],a[M],b[M],x[M],y[M],c[M],k[M],n,cnt;
struct node
{
    int x,y,w,id;
}e[N];
bool cmp(node a,node b)
{
    return a.w<b.w;
}
int find(int x)
{
    if(fa[x]==x)return fa[x];
    return fa[x]=find(fa[x]);
}
void unionn(int x,int y)
{
    x=find(x),y=find(y);
    if(x==y)return ;
    fa[x]=y;
}
int m;
void kruskal()
{
    for(int i=0;i<=n;i++)fa[i]=i;
    sort(e+1,e+1+m,cmp);
    int sum=0,cnt=0,num=0,l=0,r=0,ans=0;
    for(int i=1;i<=m;i++)
    {
        int x=find(e[i].x),y=find(e[i].y);
        if(x==y)continue;
        unionn(x,y);
        if(e[i].x==0)a[++l]=e[i].y;
        else b[++r]=e[i].x,c[r]=e[i].y;
        sum+=e[i].w;
        cnt++;
        if(cnt>n-1)break;
    }
    cout<<sum<<"\n";
    cout<<l<<"\n";
    for(int i=1;i<=l;i++)cout<<a[i]<<" ";
    cout<<'\n';
    cout<<r<<"\n";
    for(int i=1;i<=r;i++)cout<<b[i]<<" "<<c[i]<<"\n";
}
signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0),cout.tie(0);
    cin>>n;
    for(int i=1;i<=n;i++)cin>>x[i]>>y[i];
    for(int i=1;i<=n;i++)cin>>c[i];
    for(int i=1;i<=n;i++)cin>>k[i];
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            if(i==j)continue;
            int d=abs(x[i]-x[j])+abs(y[i]-y[j]);
            e[++m]=node{i,j,d*(k[i]+k[j]),0};
        }
    }
    for(int i=1;i<=n;i++){
        m++;
        e[m].x=0;
        e[m].y=i;
        e[m].w=c[i];
        e[m].id=i;
    }
    kruskal();
    return 0;
}

problem D

试了一下用贪心能拿35分(甚至还高,但是我只拿了35),正确解法最容易想的是prim,但是没学,所以只能用kruskal,看完题目,连通块需要是一片连续的,所以我们尽量把它向右合并,让它的根节点在区间右侧,那么遍历的时候就能快速的访问区间内的所有连通块

END(AFO了)