第九关——2.29模拟赛

14:26:48 不想让 你为难,你不再需要给我个答案。——杨宗纬《空白格》   

第一题 【NOIP2018模拟赛】刺客信条(AC)

分四个情况,用一个并查集维护联通性

sprt()用于算平方根

#include<bits/stdc++.h>
const int N=2002;
using namespace std;
char ch;
struct sby{
    int x,y;
    double v;
}t[N*N];
int n,x[N],y[N],f[N],xx,yy,tot,ans;
void add(int x,int y,double v)
{
    t[++tot].x=x;
    t[tot].y=y;
    t[tot].v=v;
}
bool cmp(sby a,sby b){return a.v<b.v;}
int ss(int x){return f[x]=(f[x]^x)?ss(f[x]):x;}
int main()
{
    cin>>xx>>yy>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>x[i]>>y[i];
        f[i]=i;
        add(n+1,i,y[i]);add(n+1,i,xx-x[i]);
        add(n+2,i,x[i]);add(n+2,i,yy-y[i]);
        for(int j=1;j<i;j++)
        add(i,j,sqrt((double)(x[i]-x[j])*(x[i]-x[j])+(double)(y[i]-y[j])*(y[i]-y[j]))/2);
    }
    f[n+1]=n+1;f[n+2]=n+2;
    sort(t+1,t+1+tot,cmp);
    for(ans=1;ss(n+1)^ss(n+2);ans++)f[ss(t[ans].x)]=ss(t[ans].y);
    printf("%.2lf",t[ans-1].v);
    return 0;
}

第二题 【NOIP2018模拟赛】传送门 (portal)

假设我们当前节点为i

要么在当前节点设传送门,暴力走p,再传回来,很明显我们会从最深的那个叶子传回来。

要么在p的子树中设传送门,暴力走这条边2次(下去1次,回来1次)

a[i]表示i子树中到i最远的叶子。

最后答案就是f[1]

#include<bits/stdc++.h>
#define N 1000005
#define ll long long
using namespace std;
ll f[N],g[N],a[N],c[2*N],b[2*N],head[N],n,m,next[2*N];
void add(int x,int y,int z){next[++m]=head[x];b[head[x]=m]=y;c[m]=z;}
void dfs(int k,int o)
{
    f[k]=0,g[k]=0;
    ll v=0;
    for(int i=head[k];i;i=next[i])
    {
        int p=b[i];
        if(p!=o)
        {
            dfs(p,k);
            g[k]=g[k]+2*c[i]+g[p];
            a[k]=max(a[k],a[p]+c[i]);
            f[k]=f[k]+min(2*c[i]+f[p],g[p]+c[i]-a[p]);
        }
    }
    return;
}
int main()
{
    cin>>n;
    for(int i=1;i<n;i++)
    {
        int x,y,z;
        scanf("%d%d%d",&x,&y,&z);
        add(x,y,z),add(y,x,z);
    }
    dfs(1,0);
    printf("%lld
",f[1]);
}

 第三题【NOIP2018模拟赛】黑暗之魂(darksoul)

代码繁琐。思想简单。
求图的直径。
环套树,记dis(x,y)为环上的点x到点y的最短路径。
显然,给环定一个方向,求个前缀和。对于每个环上的点x,必有一个a[x],表示按照给定的方向走,第一个满足环长显然不递减。
所以拿个线段树维护一下。一个区间加,一个区间减。

#include<bits/stdc++.h>
#define ll long long
const int N=1e6+7;
using namespace std;
int n,cnt,cir,cc,tot,mid,head,tail,flag;
int ls[N],ss[N],low[N],bb[N];
bool vis[N];
int id[N],q[N*2];
ll ans,f[N*2],size[N*2],s[N*2],dis[N*2],sumdis;
struct xz{
    int y,w,next;
}g[N*2];
struct sby{
    int x,y,w;
}a[N];
vector <int> wyb;
void add(int x,int y,int w)
{
    g[++cnt]=(xz){y,w,ls[x]};
    ls[x]=cnt;
}
void tarjan(int x,int fa)
{
    ss[x]=low[x]=++cnt;
    vis[x]=1; wyb.push_back(x);
    for (int i=ls[x];i>0;i=g[i].next)
    {
        int y=g[i].y;
        if(y==fa) continue;
        if(!ss[y])
        {
            tarjan(y,x);
            low[x]=min(low[x],low[y]);
        }
        else
        {
            if(vis[y]) low[x]=min(low[x],ss[y]);
        }
    }
    if(low[x]==ss[x])
    {
        cc++;
        int y=0,flag=0;
        if (wyb.back()!=x) flag=1,cir=cc;
        while (y!=x)
        {
            y=wyb.back();
            wyb.pop_back();
            bb[y]=cc;
            vis[y]=0;
            if (flag) id[++tot]=y;
        }
    }
}
void dfs(int x,int fa)
{
    ll max1=0,max2=0;
    for (int i=ls[x];i>0;i=g[i].next)
    {
        int y=g[i].y;
        if ((bb[y]==cir) || (y==fa)) continue;
        dfs(y,x);
        ll d=f[y]+g[i].w;
        if (d>max1)
        {
            max2=max1;
            max1=d;
        }
        else if (d>max2) max2=d;
    }
    ans=max(ans,max1+max2);
    f[x]=max1;
}
bool cmp(sby a,sby b)
{
    if (a.x==b.x)
    {
        if (a.y==b.y) return a.w<b.w;
        return a.y<b.y;
    }
    return a.x<b.x;
}
int main()
{
    cin>>n;
    for (int i=1;i<=n;i++)
    {
        cin>>a[i].x>>a[i].y>>a[i].w;
        if (a[i].x>a[i].y) 
        swap(a[i].x,a[i].y);
    }
    sort(a+1,a+n+1,cmp);   
    for(int i=1;i<=n;i++)
    {
        if(a[i].x==a[i].y) 
        flag=1;
        else
        {
            if((a[i].x==a[i-1].x)&&(a[i].y==a[i-1].y)) 
            flag=1;
            else
            {
                add(a[i].x,a[i].y,a[i].w);
                add(a[i].y,a[i].x,a[i].w);
            }
        }
    }       
    if (flag)
    {
        cir=1;
        dfs(1,0);
        printf("%lld",ans+1);
        return 0;
    }
    tarjan(1,0);
    for(int i=1;i<=tot;i++) 
    dfs(id[i],0),size[i]=f[id[i]];    
    for(int i=1;i<=tot;i++)
    {
        int d;
        if(i==1) d=id[tot];
        else d=id[i-1];
        for(int j=ls[id[i]];j>0;j=g[j].next)
        {
            if(g[j].y==d)
            {
                dis[i]=(ll)g[j].w;
                break;
            }
        }
    }    
    for(int i=tot+1;i<=2*tot;i++) 
    dis[i]=dis[i-tot],size[i]=size[i-tot];
    for(int i=1;i<=2*tot;i++) 
    s[i]=s[i-1]+dis[i];
    sumdis=s[tot];
    head=tail=1;
    q[head]=1;    
    for (int i=2;i<=2*tot;i++)
    {
        while ((head<=tail) && (s[i]-s[q[head]]>sumdis/2)) head++;
        if (head<=tail) ans=max(ans,size[i]+s[i]+size[q[head]]-s[q[head]]);
        while ((head<=tail) && (size[q[tail]]-s[q[tail]]<=size[i]-s[i])) tail--;
        q[++tail]=i;
    }    
    printf("%lld",ans+1);
    return 0;
}
原文地址:https://www.cnblogs.com/wybxz/p/12391751.html