[APIO2013]
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]的更多相关文章
- 【BZOJ】【3205】【APIO2013】机器人robot
斯坦纳树 好神啊……Orz zyf && PoPoQQQ 为啥跟斯坦纳树扯上关系了?我想是因为每个点(robot)都沿着树边汇到根的时候就全部合起来了吧= =这个好像和裸的斯坦纳树不太 ...
- bzoj3205 [Apio2013]机器人
3205: [Apio2013]机器人 Time Limit: 15 Sec Memory Limit: 128 MBSubmit: 953 Solved: 227[Submit][Status] ...
- [BZOJ3206][APIO2013]道路费用(最小生成树)
3206: [Apio2013]道路费用 Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 568 Solved: 266[Submit][Status ...
- [BZOJ3205][APIO2013]Robot(斯坦纳树)
3205: [Apio2013]机器人 Time Limit: 15 Sec Memory Limit: 128 MBSubmit: 1007 Solved: 240[Submit][Status ...
- [Bzoj3206][Apio2013]道路费用(kruscal)(缩点)
3206: [Apio2013]道路费用 Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 536 Solved: 252[Submit][Status ...
- [Bzoj3205][Apio2013]机器人(斯坦纳树)(bfs)
3205: [Apio2013]机器人 Time Limit: 15 Sec Memory Limit: 128 MBSubmit: 977 Solved: 230[Submit][Status] ...
- APIO2013 tasksauthor
喜闻乐见的提答题,这道题还是蛮有趣的 数据结构题写得心塞,来一道提答意思意思 如果喜欢这类题的话还可以去做做uoj83. 这题是给出了两个问题,一个最短路,一个无向图染色问题. Data 1 Floy ...
- BZOJ3206 [Apio2013]道路费用
首先我们强制要求几条待定价的边在MST中,建出MST 我们发现这个MST中原来的边是一定要被选上的,所以可以把点缩起来,搞成一棵只有$K$个点的树 然后$2^K$枚举每条边在不在最终的MST中,让在最 ...
- UOJ #109「APIO2013」TASKSAUTHOR
貌似是最入门的题答题 刚好我就是入门选手 就这样吧 UOJ #109 题意 太热了不讲了 $ Solution$ 第一个点:$ 105$个数字卡掉$ Floyd$ 直接$101$个点无出边一次询问就好 ...
随机推荐
- pickle使用及案例
一.字典格式数据源写入数据库文件 #!/usr/bin/env python # -*- coding:utf-8 -*- import pickle accounts ={1000:'alex', ...
- mvc架构模式概念
MVC模式是"Model-View-Controller"的缩写,中文翻译为"模式-视图-控制器".MVC应用程序总是由这三个部分组成.Event(事件)导致C ...
- Flask 蓝图(Blueprint)
蓝图使用起来就像应用当中的子应用一样,可以有自己的模板,静态目录,有自己的视图函数和URL规则,蓝图之间互相不影响.但是它们又属于应用中,可以共享应用的配置.对于大型应用来说,我们可以通过添加蓝图来扩 ...
- python解释NTFS runlist的代码(文章转自北亚数据恢复张宇工程师)
代码如下: 执行效果如下:root@zhangyu-VirtualBox:~/NTFS-5# python3 read_runlist.py mft_source.img ***参数数量或格式错误! ...
- angular路由守卫
路由守卫是指当用户满足了某些要求之后才可以离开或者进入某个页面或者场景的时候使用.比如说只有当用户填写了用户名和密码之后才可以进入首页,比如说用户离开某个页面时明月保存信息提示用户是否保存信息后再离 ...
- Python内置函数(45)——ascii
英文文档: ascii(object) As repr(), return a string containing a printable representation of an object, b ...
- 阿里云API网关(9)常见问题
网关指南: https://help.aliyun.com/document_detail/29487.html?spm=5176.doc48835.6.550.23Oqbl 网关控制台: https ...
- python常用运算符
1. / 浮点除法,就算分子分母都是int类型,也返回float类型,比如我们用4/2,返回2.0 2. // 整数除法,根据分子分母的不同组合,返回的值有差异. 正数//正数,取整,比如5//3,返 ...
- c# IPC实现本机进程之间的通信
IPC可以实现本地进程之间通信.这种用法不是太常见,常见的替代方案是使用wcf,remoting,web service,socket(tcp/pipe/...)等其他分布式部署方案来替代进程之间的通 ...
- c#:实现动态编译,并实现动态MultiProcess功能(来自python multiprocess的想法)
由于之前一直遇到一些关于并行进行数据处理的时效果往往不好,不管是c#还是java程序都是一样,但是在Python中通过multiprocess实现同样的功能时,却发现确实可以提高程序运行的性能,及服务 ...