2016 Benelux Algorithm Programming Contest (BAPC 16)

Time:2018.4.27  17:00-22:00

Link


A

题意

分析

几何最短路,留坑


B    solved by ym

题意

ym:按题意模拟即可 


C    solved by ym

题意

ym:赛时czh的代码FST了,按题意模拟不断删点,实际上和拓扑排序删点相似

#include<bits/stdc++.h>
using namespace std;

int head[300003*2],nxt[300003*2],to[300003*2],tot;
int C,P,X,L;
int d[200005],del[200005];
bool vis[200005];


void add(int u,int v)
{
    ++tot;
    to[tot]=v;
    nxt[tot]=head[u];
    head[u]=tot;
}

void topsort()
{
    queue<int>q;
    q.push(L);
    vis[L]=1;
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        for(int i=head[u];i;i=nxt[i])
        {
            int v=to[i];
            del[v]++;
            if(!vis[v]&&del[v]>=((d[v]+1)/2))
            {
                vis[v]=1;
                q.push(v);
            }
        }
    }
}

int main()
{
    scanf("%d%d%d%d",&C,&P,&X,&L);
    int u,v;
    for(int i=1;i<=P;i++)
    {
        scanf("%d%d",&u,&v);
        d[u]++;
        d[v]++;
        add(u,v);
        add(v,u);
    }
    topsort();
    if(vis[X])
    {
        cout<<"leave"<<endl;
    }
    else
        cout<<"stay"<<endl;
    return 0;
}

D

题意

现有n艘船需要通过桥,但桥很累不想一直连通,所以在“闲”的时候可以不连通,但每艘船不可以等待超过30min,升/降桥会花费60s,每艘船通过花费20s,船一艘一艘的通过,给出每艘船到达桥的时间T_i,问船工作的最小时间(升降+连通) ( n<=4000,T_i<=1e5,i<j && T_i+20<=T_j )

分析

ym:令f_i为前艘船通过的最小时间,枚举和i一起通过的船j(j<=i),转移即可

时间复杂度O(n^2)

#include<bits/stdc++.h>
using namespace std;

int dp[4005],n,a[4005];

int main()
{

    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        dp[i]=1000000+7;
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
    }
    dp[1]=140;
    for(int i=2;i<=n;i++)
    {
        for(int j=1;j<=i;j++)
        {
            dp[i]=min(dp[i], dp[j-1]+120+20+a[i]-min(a[j]+1800,a[i]-(i-j)*20));
        }
    }
    printf("%d\n",dp[n]);
    return 0;
}

E

题意

给一个n个点m条边的无向图,给出起点到终点的路径最大值,问满足路径和小于max的所有路径中每条路径的最大值最小(n<=1e4,m<=1e5,w<=1e9)

分析

ym:比赛时候天马行空的考虑完全图路径很多的情况==,实际上至于只需要关注每一个点和边的访问次数,便能正确得出时间复杂度,例如在有权的无向图中的单源最短路,由于每个点只会被取出一次所以时间复杂度为(VlogV),回到此题,二分答案(最短路具有单调性)最短路检查即可(边权w如果大于mid,相当于看做不选择这条边即可,在剩下的点中求最短路径)

时间复杂度O(nlog2n)

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn=210000;
priority_queue<pair<LL,int>,vector<pair<LL,int> >,greater<pair<LL,int> > > q;
const LL INF=1e18;
LL dis[110000];
int vis[110000];
int n,m,x;

int head[maxn],nxt[maxn],to[maxn],tot;
LL w[210000];

void add(int u,int v,int c)
{
    ++tot;
    to[tot]=v;
    w[tot]=c;
    nxt[tot]=head[u];
    head[u]=tot;
}

LL dij(int limt)
{
    for(int i=1;i<=n;i++)
        dis[i]=INF,vis[i]=0;
    dis[1]=0;
    q.push(make_pair(0,1));
    while(!q.empty())
    {
        int now=q.top().second;
        q.pop();
        if(vis[now])
            continue;
        vis[now]=1;
        for(int i=head[now];i!=0;i=nxt[i])
        {
            if (w[i]<=limt&&dis[to[i]]>dis[now]+w[i])
            {    dis[to[i]]=dis[now]+w[i];
                q.push(make_pair(dis[to[i]],to[i]));
            }
        }
    }
    return dis[n];

}
LL dist;
int ans;
int check(int x)
{
    return dij(x)<=dist;
}

int main()
{
    scanf("%d%d%d", &n, &m,&x);
    int u,v;
    int c;
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d%d",&u,&v,&c);
        add(u,v,c);
        add(v,u,c);
    }
    dist=dij(1000000000);
    dist=dist*(100LL+x)/100;
    int l=1,r=1000000000;
    while (l<=r)
    {
          int mid=(l+r)/2;
          if (check(mid)) ans=mid,r=mid-1;
          else l=mid+1;
    }
    printf("%d\n",ans);
    return 0;
}

F

题意

分析

几何模拟,留坑


G

题意

 

分析

 ym:可做几何,待补


H

题意

 

分析

ym:爆搜剪纸,待补


I      solved by czh&ym

题意

ym:按题意模拟即可


J    solved by ym&czh

题意

分别给出n个学生和n个导师的二维坐标,定义两点的dis:|x1-x2|+|y1-y2|,现要一 一配对,要使最大的dis最小,问每个最大所有情况最小的dis

分析

ym:算法理解不深刻,只会套板子

         二分图是根据边集,不断找增广路,故可以二分答案,二分图check,即在找增广路的时候加上约束条件

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn = 100+7;

int n,f[maxn],v[maxn];
ll sx[maxn],sy[maxn],tx[maxn],ty[maxn];

ll _abs(ll x){
    if(x>0) return x;
    else return -x;
}

ll dis(int i,int j){
    return _abs(sx[i]-tx[j])+_abs(sy[i]-ty[j]);
}

bool found(int x,ll mid)
{
    for(int i=1;i<=n;i++)
    {
        if(dis(x,i)<=mid&&!v[i])
        {
            v[i]=1;
            if(f[i]==0||found(f[i],mid))
            {
                f[i]=x;
                return true;
            }
        }
    }
    return false;
}

bool check(ll mid)
{
    for(int i=1;i<=n;i++)
        f[i]=0;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++) v[j]=0;
        if(!found(i,mid))
            return false;
    }
    return true;
}

int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%lld%lld",&sx[i],&sy[i]);
    for(int i=1;i<=n;i++)
        scanf("%lld%lld",&tx[i],&ty[i]);
    bool flag=true;
    ll l=0,r=1000000000;
    while(l<r)
    {
        ll mid=(l+r)/2;
        if(check(mid))
        {
            r=mid;
        }
        else
            l=mid+1;
    }
    printf("%lld\n",l);
    return 0;
}

K

题意

给出长度为L的圆形跑道,每S米至少放一个人,问方案数 

分析

ym:dp待补 


L   solved by czh&ym

题意

ym:排序后检查相邻3项能否形成三角形即可


Summary

Ym这次表现看上去不错,,其实很惨,数据有锅,Link以Update,kattis数据正确(甚至很强,E卡我两个小时),以后比赛多读几道题,利于补题呀!!!

Czh:

posted @ 2018-04-28 09:08  Deadlined  阅读(483)  评论(0编辑  收藏  举报