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. JavaScript 相关知识

    一.数组   var a = [1,2,3,4]; console.log(a.length); a.push(5); console.log(a); // [1, 2, 3, 4, 5] var r ...

  2. Hibernate之SQL查询

    Hibernate支持使用原生的SQL语句进行查询.使用原生的SQL的好处是:可以利用某些数据库的特性(不同的数据库SQL 语法会有所差异), 将原有的使用JDBC作为持久层技术的应用 ,迁移到使用H ...

  3. mysql5.7在windows下面的主从复制配置

    目标:自动同步Master 服务器上面的Demo数据库到Slave 服务器的Demo数据库中. 对于一些操作系统比较强而使用频率又不高的东西,往往好久不去弄就忘记了,所以要经常记录起来,方便日后查阅. ...

  4. [知识梳理]课本1&2.1-2.5

    面向对象的语言 出发点:更直接地描述客观世界中存在的事物(对象)以及它们之间的关系. 特点: 是高级语言. 将客观事物看作具有属性和行为的对象. 通过抽象找出同一类对象的共同属性和行为,形成类. 通过 ...

  5. linux系统命令学习系列-例行任务管理at命令

    先来复习一下上节内容: 切换用户身份命令su 以root身份执行操作命令sudo 作业:给user1配置sudo权限,不用密码,可执行useradd命令 在/etc/sudoers文件中添加如下配置项 ...

  6. Jenkins 安装、配置与项目新建及构建

    1.Jenkins的安装与配置 1.1 java环境配置 Jenkins基于Java, Linux下安装java只要配置java环境变量即可. 首先,解压java到相应目录,我一般习惯把安装的软件放到 ...

  7. python中 return 的用法

    return 语句就是讲结果返回到调用的地方,并把程序的控制权一起返回 程序运行到所遇到的第一个return即返回(退出def块),不会再运行第二个return. 要返回两个数值,写成一行即可: de ...

  8. ABP CORE 框架入门视频教程《电话薄》基于 Asp.NET Core2.0 EF Core

    ABP框架简介 ABP是"ASP.NET Boilerplate Project (ASP.NET样板项目)"的简称. ASP.NET Boilerplate是一个用最佳实践和流行 ...

  9. shiro的sessionManager类继承结构及主要类方法

    shiro1.3.2 sessionManage的作用是对会话进行管理. 1.类结构 2.主要接口介绍 SessionManager: 包括两个方法,一个是新建会话,一个是通过key获取会话 Vali ...

  10. idea中使用svn,忽略本地修改的指定的文件

    1.打开version control 2.可以查看目前忽略的文件 3.配置要忽略的文件 4.可以用通配符忽略匹配的文件 还有第二种方法,那就是: 在svn提交的界面,如果是没有加入到version- ...