2016 Benelux Algorithm Programming Contest (BAPC 16)
Time:2018.4.27 17:00-22:00
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: