A.机器人

题目大意:给定一个n*m的地图,有一些障碍物和k个机器人,你每次可以选择一个机器人往任意一个方向推,遇到转向器会转向,两个编号相邻的机器人可以合并,求最少推多少次可以全部合并。

$n,m\leqslant 500 k\leqslant 9$

题解:用f[i][j][k][l]表示i到j的机器人在(k,l)合并的最小次数,那么当(k',l')推一次可以到(k,l)的时候,它可以从f[i][j][k'][l']+1转移。当然,它还可以从f[i][p][k][l]+f[p+1][j][k][l]转移,所以我们先计算出

所有点推一次到哪里,每次做完一个f[i][j]之后,就做一次spfa。

但是spfa会T,并不能过。我们考虑开两个队列,在spfa之前把起始的位置拍好序扔到队列1,然后每次取出两个队列队头较小的松弛,松弛到的点加入队列2,这样可以保证队列1和队列2有序,spfa就进化为了bfs,排序最好用O(n)的计数排序,跑的飞快。

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#include<algorithm>
#define INF 32639
using namespace std;
inline int read()
{
int x = , f = ; char ch = getchar();
while(ch < '' || ch > ''){ if(ch == '-') f = -; ch = getchar();}
while(ch >= '' && ch <= ''){x = x * + ch - '';ch = getchar();}
return x * f;
} unsigned short d[][][][];int mark[][][],top=;
int n,h,w,cnt=,L,R;
int v[],sa[];
char st[][];
struct P{short x,y;
P(short x=,short y=):x(x),y(y){}
bool operator !(){return x==&&y==;}
}pos[],to[][][],q[];
bool b[][];
const int dis[][]={{,},{,},{,-},{-,}};
queue<P> q1,q2; P dfs(int x,int y,int dir)
{
if(mark[x][y][dir]==cnt) return to[x][y][dir]=P(-,-);mark[x][y][dir]=cnt;
if(!(!to[x][y][dir])) return to[x][y][dir];
int pre=dir;
if(st[x][y]=='A') dir=(dir+)%;
if(st[x][y]=='C') dir=(dir+)%;
int xx=x+dis[dir][],yy=y+dis[dir][];
if(xx<||yy<||xx>h||yy>w||st[xx][yy]=='x') return to[x][y][pre]=P(x,y);
return to[x][y][pre]=dfs(xx,yy,dir);
} void spfa()
{
memset(v,,sizeof(v));
for(int i=;i<=top;i++)v[d[L][R][q[i].x][q[i].y]]++;
for(int i=;i<=INF;i++)v[i]+=v[i-];
for(int i=;i<=top;i++) sa[v[d[L][R][q[i].x][q[i].y]]--]=i;
for(int i=;i<=top;i++) q1.push(q[sa[i]]);
top=;
while((!q1.empty())||(!q2.empty()))
{
P now;
if(q1.empty()||((!q2.empty())&&d[L][R][q1.front().x][q1.front().y]>d[L][R][q2.front().x][q2.front().y]))
now=q2.front(),q2.pop();
else
now=q1.front(),q1.pop();
b[now.x][now.y]=;
for(int i=;i<;i++)
{
P t=to[now.x][now.y][i];
if(t.x==-||t.y==-) continue;
if(d[L][R][now.x][now.y]+<d[L][R][t.x][t.y])
{
d[L][R][t.x][t.y]=d[L][R][now.x][now.y]+;
if(!b[t.x][t.y])
{
b[t.x][t.y]=;
q2.push(t);
}
}
} }
} int main()
{
n=read();w=read();h=read();
memset(d,,sizeof(d));
for(int i=;i<=h;i++)
{
scanf("%s",st[i]+);
for(int j=;j<=w;j++)
if(st[i][j]>''&&st[i][j]<='')
pos[st[i][j]-'']=P(i,j);
}
for(int i=;i<=h;i++)
for(int j=;j<=w;j++)
if(st[i][j]!='x')
for(int k=;k<;k++)
++cnt,dfs(i,j,k);
for(int i=;i<=n;i++)
{
b[pos[i].x][pos[i].y]=;q[++top]=pos[i];
L=R=i;d[i][i][pos[i].x][pos[i].y]=;spfa();
}
for(int l=,j;l<=n;l++)
for(int i=;(j=i+l-)<=n;i++)
{
for(int x=;x<=h;x++)
for(int y=;y<=w;y++)
{
for(int k=i;k<j;k++)
d[i][j][x][y]=min(d[i][j][x][y],(unsigned short)(d[i][k][x][y]+d[k+][j][x][y]));
if(d[i][j][x][y]<INF)
q[++top]=P(x,y),b[x][y]=;
}
L=i;R=j;spfa();
}
unsigned short ans=;
for(int i=;i<=h;i++)
for(int j=;j<=w;j++)
ans=min(ans,d[][n][i][j]);
if(ans<) printf("%u\n",ans);
else puts("-1");
return ;
}

B.[Apio2013]道路费用

$n\leqslant 10^{5},m\leqslant 3*10^{5},k\leqslant 20$

题解:强制选这K条边,然后我们发现K条边把整个图割成了K+1块,每一块内选的边肯定是相同的。我们把这几块缩点,然后枚举每条边选不选,对每种情况,暴力算出每条边的最大长度,通过dp算出这种情况的答案就可以啦。

复杂度$mlogm+k^{2}*2^{k}$

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
#define INF 200000000000000000LL
#define MN 100000
#define MM 300000
#define MK 20
using namespace std;
inline int read()
{
int x = , f = ; char ch = getchar();
while(ch < '' || ch > ''){ if(ch == '-') f = -; ch = getchar();}
while(ch >= '' && ch <= ''){x = x * + ch - '';ch = getchar();}
return x * f;
} struct edge{
int from,to;ll w;int kind;
}e[MM+MK+],ek[MK+],e3[MK+];
struct nedge{int to,next,kind;}e2[MN*+];
ll ans=,sum[MK+],p[MN+],val[MK+],mn[MK+];
int n,m,K,cnt=,s[MN+],head[MN+],cn=,bel[MN+],dep[MK+],fa2[MK+];
bool mark[MN+],b[MK+]; bool cmp(edge x,edge y){return x.w<y.w||(x.w==y.w&&x.kind>y.kind);}
int find(int x)
{
return !s[x]?x:s[x]=find(s[x]);
} void ins(int f,int t,int kind=)
{
e2[++cnt]=(nedge){t,head[f],kind};head[f]=cnt;
e2[++cnt]=(nedge){f,head[t],kind};head[t]=cnt;
} void kruscal()
{
for(int i=;i<=K;i++)
{
int x=find(ek[i].from),y=find(ek[i].to);
s[x]=y,ins(ek[i].from,ek[i].to,);
}
for(int i=;i<=m;i++)
{
int x=find(e[i].from),y=find(e[i].to);
if(x!=y)s[x]=y,ins(e[i].from,e[i].to,);
}
} void getv(int x)
{
mark[x]=;bel[x]=cn;val[cn]+=p[x];
for(int i=head[x];i;i=e2[i].next)
if(!mark[e2[i].to]&&!e2[i].kind)
getv(e2[i].to);
} void dp(int x,int fa)
{
sum[x]=val[x];fa2[x]=fa;
for(int i=head[x];i;i=e2[i].next)
if(e2[i].to!=fa)
{
dep[e2[i].to]=dep[x]+;
dp(e2[i].to,x);sum[x]+=sum[e2[i].to];
}
}
int tms=;
void solve()
{
ll tot=;cnt=;
for(int i=;i<=cn;i++)s[i]=,head[i]=,mn[i]=INF;
for(int i=;i<=K;i++)
if(b[i])
{
int x=find(ek[i].from),y=find(ek[i].to);
if(x==y)return;s[x]=y;ins(ek[i].from,ek[i].to);
}
tms++;
for(int i=;i<=K;i++)
{
int x=find(e3[i].from),y=find(e3[i].to);
if(x!=y) s[x]=y,ins(e3[i].from,e3[i].to);
}
dp(,);
for(int i=;i<=K;i++)
{
int u=e3[i].from,v=e3[i].to;
if(dep[u]<dep[v]) swap(u,v);
while(dep[u]>dep[v]) mn[u]=min(mn[u],e3[i].w),u=fa2[u];
while(u!=v)
{
mn[u]=min(mn[u],e3[i].w);
mn[v]=min(mn[v],e3[i].w);
u=fa2[u],v=fa2[v];
}
}
for(int i=;i<=K;i++) if(b[i])
{
int u=ek[i].from,v=ek[i].to;
if(dep[u]<dep[v]) swap(u,v);
tot+=1LL*mn[u]*sum[u];
}
ans=max(ans,tot);
} void dfs(int x)
{
if(x>K)
{
solve();
return;
}
b[x]=;dfs(x+);
b[x]=;dfs(x+);
} int main()
{
n=read();m=read();K=read();
for(int i=;i<=m;i++)
e[i].from=read(),e[i].to=read(),e[i].w=read();
for(int i=;i<=K;i++)
ek[i].from=read(),ek[i].to=read();
for(int i=;i<=n;i++)p[i]=read();
sort(e+,e+m+,cmp);kruscal();
for(int i=;i<=n;i++)if(!mark[i]) ++cn,getv(i);
cnt=;
for(int i=;i<=cn;i++) s[i]=;
for(int i=;i<=m+K;i++) if(!e[i].kind)
{
int x=bel[e[i].from],y=bel[e[i].to],f1=find(x),f2=find(y);
if(f1!=f2) s[f1]=f2,e3[++cnt]=(edge){x,y,e[i].w,};
}
for(int i=;i<=K;i++) ek[i].from=bel[ek[i].from],ek[i].to=bel[ek[i].to];
dfs();
cout<<ans;
return ;
}

[APIO2013]的更多相关文章

  1. 【BZOJ】【3205】【APIO2013】机器人robot

    斯坦纳树 好神啊……Orz zyf && PoPoQQQ 为啥跟斯坦纳树扯上关系了?我想是因为每个点(robot)都沿着树边汇到根的时候就全部合起来了吧= =这个好像和裸的斯坦纳树不太 ...

  2. bzoj3205 [Apio2013]机器人

    3205: [Apio2013]机器人 Time Limit: 15 Sec  Memory Limit: 128 MBSubmit: 953  Solved: 227[Submit][Status] ...

  3. [BZOJ3206][APIO2013]道路费用(最小生成树)

    3206: [Apio2013]道路费用 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 568  Solved: 266[Submit][Status ...

  4. [BZOJ3205][APIO2013]Robot(斯坦纳树)

    3205: [Apio2013]机器人 Time Limit: 15 Sec  Memory Limit: 128 MBSubmit: 1007  Solved: 240[Submit][Status ...

  5. [Bzoj3206][Apio2013]道路费用(kruscal)(缩点)

    3206: [Apio2013]道路费用 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 536  Solved: 252[Submit][Status ...

  6. [Bzoj3205][Apio2013]机器人(斯坦纳树)(bfs)

    3205: [Apio2013]机器人 Time Limit: 15 Sec  Memory Limit: 128 MBSubmit: 977  Solved: 230[Submit][Status] ...

  7. APIO2013 tasksauthor

    喜闻乐见的提答题,这道题还是蛮有趣的 数据结构题写得心塞,来一道提答意思意思 如果喜欢这类题的话还可以去做做uoj83. 这题是给出了两个问题,一个最短路,一个无向图染色问题. Data 1 Floy ...

  8. BZOJ3206 [Apio2013]道路费用

    首先我们强制要求几条待定价的边在MST中,建出MST 我们发现这个MST中原来的边是一定要被选上的,所以可以把点缩起来,搞成一棵只有$K$个点的树 然后$2^K$枚举每条边在不在最终的MST中,让在最 ...

  9. UOJ #109「APIO2013」TASKSAUTHOR

    貌似是最入门的题答题 刚好我就是入门选手 就这样吧 UOJ #109 题意 太热了不讲了 $ Solution$ 第一个点:$ 105$个数字卡掉$ Floyd$ 直接$101$个点无出边一次询问就好 ...

随机推荐

  1. python day1 基本语法作业

    一.过7 start =1 while start<=10: if start !=7: print(start) start +=1 二.100以内的和 sum = 0 start = 1 w ...

  2. DML数据操作语言之常用函数

    所谓函数,就是输入某一值,得到相应的输出结果的功能.相当于一个加工厂,给了原料,最终产出成品. 其中原料 就是参数(parameter). 产品 就是返回值. 函数大致可以分为以下五个种类: 算术函数 ...

  3. ASP.NET MVC中错误处理方式

    /// <summary> /// 标记了HandleError,并指明错误处理页为AboutError.aspx /// </summary> /// <returns ...

  4. 机器学习中的K-means算法的python实现

    <机器学习实战>kMeans算法(K均值聚类算法) 机器学习中有两类的大问题,一个是分类,一个是聚类.分类是根据一些给定的已知类别标号的样本,训练某种学习机器,使它能够对未知类别的样本进行 ...

  5. Python-socket网络编程-Day8

    目录Day8-Python socket 11.Socket 11.1.socket和file的区别: 11.2.WEB服务应用: 21.3.更多功能 21.4.socket方法: 41.5. 服务端 ...

  6. HTTP协议扫盲(六)InputStream的复用

    一.问题提出 在进行网关引擎开发时,获取到一个http请求的inputstream后,可能要多次利用它进行read操作.由于流读过一次就不能再读了,所以需要实现InputStream的复制. 而Inp ...

  7. Extensions in UWP Community Toolkit - Mouse Cursor

    概述 UWP Community Toolkit Extensions 中有一个为 Mouse 提供的扩展 - Mouse Cursor Extensions,本篇我们结合代码详细讲解 Mouse C ...

  8. 使用net.sf.cssbox实现网页截图

    需要引用包,在pom.xml中添加引用: <dependency> <groupId>net.sf.cssbox</groupId> <artifactId& ...

  9. Ubuntu+vscode打不开

    前沿: vscode链接 参考链接 问题: 之前在Ubuntu上安装chrome, 结果chrome没装成功, 还把vscode给qiu坏了, 貌似是当时安装chrome时提示要升级一个包. 后来发现 ...

  10. vue+iview实现动态路由和权限验证

    github上关于vue动态添加路由的例子很多,本项目参考了部分项目后,在iview框架基础上完成了动态路由的动态添加和菜单刷新.为了帮助其他需要的朋友,现分享出实现逻辑,欢迎一起交流学习. Gith ...