题目链接


Solution

  1. 非正解

    似乎比较蛇啊,先个一个部分分做法,最短路+\(DP\).

    在求最短路的堆或者队列中存储元素 \(dis_{i,j}\) 代表 \(i\) 这个节点,走了 \(j\) 条边的距离.

    然后跑堆优化 \(Dijkstra\) 或者 SPFA 即可.

    复杂度 \(O(N*nlog(n))\).

    其中 \(N\) 代表要走的边条数, \(n\) 代表节点数 . 但是这题 \(N\) 有 \(10^6\) ...

    洛谷上可以过掉 \(49\) 分.

    不过只要 \(N\) 小一点,这个算法明显更优啊...

  2. 正解

    虽然这题 \(N\) 很大,但是 \(n\) 超级小啊... 只有 \(10^2\) ...

    于是可以用 \(Floyd\) 跑最短路,然后呢??

    倍增。

    令 \(dis_{i,j,k}\) 代表从 \(i\) 到 \(j\) 走了 \(2^k\) 条边的最小距离.

    然后 \(Floyd\) 转移的时候利用和倍增跳 LCA 差不多的方式转移即可.

    (具体可以看代码)

    时间复杂度 \(O(n^3*log(N))\).

另外此题还需要一点离散化.


Code

49分:

#include<bits/stdc++.h>
using namespace std;
const int maxn=10008;
struct sj{int to,next,w;}a[maxn];
struct node{int u,k;};
int head[maxn],size,cnt;
int x[maxn],y[maxn],w[maxn];
int to[maxn],num,n,t,S,E;
map<int,int>dis[508],v[508];
map<int,int>js[508];
map<int,int>kkk; int read()
{
char ch=getchar(); int f=1,w=0;
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch<='9'&&ch>='0'){w=w*10+ch-'0';ch=getchar();}
return f*w;
} void add(int x,int y,int w)
{
a[++size].to=y;
a[size].next=head[x];
head[x]=size;
a[size].w=w;
} void spfa()
{
queue<node>q;
q.push((node){S,0});
dis[S][0]=0; v[S][0]=1;
js[S][0]++;
while(!q.empty())
{
node x=q.front();q.pop();
int u=x.u,k=x.k;
if(k==n)continue;
for(int i=head[u];i;i=a[i].next)
{
int tt=a[i].to;
if(!js[tt][k+1])dis[tt][k+1]=192608173,js[tt][k+1]++;
if(dis[tt][k+1]>dis[u][k]+a[i].w)
{
dis[tt][k+1]=dis[u][k]+a[i].w;
if(!v[tt][k+1])
{
q.push((node){tt,k+1});
v[tt][k+1]=1;
}
}
}
v[u][k]=0;
}
} void pre()
{
sort(to+1,to+num+1);
int last=192608173;
for(int i=1;i<=num;i++)
{
if(to[i]!=last)
{
kkk[to[i]]=++cnt;
last=to[i];
}
}
for(int i=1;i<=t;i++)
{
x[i]=kkk[x[i]],y[i]=kkk[y[i]];
//cout<<x[i]<<' '<<y[i]<<endl;
add(x[i],y[i],w[i]);
add(y[i],x[i],w[i]);
}
} int main()
{
n=read(); t=read(); S=read(); E=read();
for(int i=1;i<=t;i++)
{
w[i]=read();
x[i]=read(); y[i]=read();
to[++num]=x[i]; to[++num]=y[i];
}
pre(); S=kkk[S],E=kkk[E];
spfa();
cout<<dis[E][n]<<endl;
}


100分:

#include<bits/stdc++.h>
using namespace std;
const int maxn=10008;
struct node{int u,k;};
int cnt;
int x[maxn],y[maxn],w[maxn];
int to[maxn],num,n,t,S,E;
int dis[508][508][22],ans[508][508];
map<int,int>kkk; int read()
{
char ch=getchar(); int f=1,w=0;
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch<='9'&&ch>='0'){w=w*10+ch-'0';ch=getchar();}
return f*w;
} void floyd()
{
for(int p=1;p<=20;p++)
for(int k=1;k<=cnt;k++)
for(int i=1;i<=cnt;i++)
for(int j=1;j<=cnt;j++)
dis[i][j][p]=min(dis[i][j][p],dis[i][k][p-1]+dis[k][j][p-1]);
} void getans()
{
memset(ans,127/2,sizeof(ans));
int t=0,p=0;
ans[0][S]=0;
while(n)
{
if(n&1)
{
t=!t;
for(int i=1;i<=cnt;i++)
{
ans[t][i]=2e9;
for(int j=1;j<=cnt;j++)
ans[t][i]=min(ans[t][i],ans[!t][j]+dis[i][j][p]);
}
}
p++; n/=2;
}
cout<<ans[t][E];
}
#include<bits/stdc++.h>
using namespace std;
const int maxn=10008;
struct node{int u,k;};
int cnt;
int x[maxn],y[maxn],w[maxn];
int to[maxn],num,n,t,S,E;
int dis[508][508][22],ans[508][508];
map<int,int>kkk; int read()
{
char ch=getchar(); int f=1,w=0;
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch<='9'&&ch>='0'){w=w*10+ch-'0';ch=getchar();}
return f*w;
} void floyd()
{
for(int p=1;p<=20;p++)
for(int k=1;k<=cnt;k++)
for(int i=1;i<=cnt;i++)
for(int j=1;j<=cnt;j++)
dis[i][j][p]=min(dis[i][j][p],dis[i][k][p-1]+dis[k][j][p-1]);
} void getans()
{
memset(ans,127/2,sizeof(ans));
int t=0,p=0;
ans[0][S]=0;
while(n)
{
if(n&1)
{
t=!t;
for(int i=1;i<=cnt;i++)
{
ans[t][i]=2e9;
for(int j=1;j<=cnt;j++)
ans[t][i]=min(ans[t][i],ans[!t][j]+dis[i][j][p]);
}
}
p++; n/=2;
}
cout<<ans[t][E];
} void pre()
{
sort(to+1,to+num+1);
int last=192608173;
for(int i=1;i<=num;i++)
{
if(to[i]!=last)
{
kkk[to[i]]=++cnt;
last=to[i];
}
}
for(int i=1;i<=t;i++)
{
x[i]=kkk[x[i]],y[i]=kkk[y[i]];
dis[x[i]][y[i]][0]=dis[y[i]][x[i]][0]=w[i];
}
} int main()
{
n=read(); t=read(); S=read(); E=read();
memset(dis,127/3,sizeof(dis));
for(int i=1;i<=t;i++)
{
w[i]=read();
x[i]=read(); y[i]=read();
to[++num]=x[i]; to[++num]=y[i];
}
pre(); S=kkk[S],E=kkk[E];
floyd();
getans();
} void pre()
{
sort(to+1,to+num+1);
int last=192608173;
for(int i=1;i<=num;i++)
{
if(to[i]!=last)
{
kkk[to[i]]=++cnt;
last=to[i];
}
}
for(int i=1;i<=t;i++)
{
x[i]=kkk[x[i]],y[i]=kkk[y[i]];
dis[x[i]][y[i]][0]=dis[y[i]][x[i]][0]=w[i];
}
} int main()
{
n=read(); t=read(); S=read(); E=read();
memset(dis,127/3,sizeof(dis));
for(int i=1;i<=t;i++)
{
w[i]=read();
x[i]=read(); y[i]=read();
to[++num]=x[i]; to[++num]=y[i];
}
pre(); S=kkk[S],E=kkk[E];
floyd();
getans();
}

[USACO07NOV]牛继电器Cow Relays (最短路,DP)的更多相关文章

  1. [USACO07NOV]牛继电器Cow Relays

    题目描述 给出一张无向连通图,求S到E经过k条边的最短路. 输入输出样例 输入样例#1: 2 6 6 4 11 4 6 4 4 8 8 4 9 6 6 8 2 6 9 3 8 9 输出样例#1: 10 ...

  2. P2886 [USACO07NOV]牛继电器Cow Relays

    题目描述 For their physical fitness program, N (2 ≤ N ≤ 1,000,000) cows have decided to run a relay race ...

  3. 洛谷P2886 [USACO07NOV]牛继电器Cow Relays

    题意很简单,给一张图,把基本的求起点到终点最短路改成求经过k条边的最短路. 求最短路常用的算法是dijkstra,SPFA,还有floyd. 考虑floyd的过程: c[i][j]=min(c[i][ ...

  4. Luogu 2886 [USACO07NOV]牛继电器Cow Relays

    BZOJ 1706权限题. 倍增$floyd$. 首先这道题有用的点最多只有$200$个,先离散化. 设$f_{p, i, j}$表示经过$2^p$条边从$i$到$j$的最短路,那么有转移$f_{p, ...

  5. [LUOGU] P2886 [USACO07NOV]牛继电器Cow Relays

    https://www.luogu.org/problemnew/show/P2886 给定无向连通图,求经过k条边,s到t的最短路 Floyd形式的矩阵乘法,同样满足结合律,所以可以进行快速幂. 离 ...

  6. [luoguP2886] [USACO07NOV]牛继电器Cow Relays(矩阵)

    传送门 矩阵快速幂,本质是floyd 把 * 改成 + 即可 注意初始化 因为只有100条边,所以可以离散化 #include <cstdio> #include <cstring& ...

  7. 洛谷 P2886 [USACO07NOV]牛继电器Cow Relays

    题面 解题思路 ## floyd+矩阵快速幂,跟GhostCai爷打赌用不用离散化,最后完败..GhostCai真是tql ! 有个巧妙的方法就是将节点重新编号,因为与节点无关. 代码 #includ ...

  8. luogu题解 P2886 【牛继电器Cow Relays】-经过K边最短路&矩阵

    题目链接: https://www.luogu.org/problemnew/show/P2886 Update 6.16 最近看了下<算法导论>,惊奇地发现在在介绍\(APSP\) \( ...

  9. [洛谷P2886] 牛继电器Cow Relays

    问题描述 For their physical fitness program, N (2 ≤ N ≤ 1,000,000) cows have decided to run a relay race ...

随机推荐

  1. cv2.getPerspectiveTransform 透视变换

    简介 透视变换(Perspective Transformation)是将成像投影到一个新的视平面(Viewing Plane),也称作投影映射(Projective Mapping).如图1,通过透 ...

  2. SpringMVC-请求参数的绑定

    绑定的机制 表单提交的数据都是k=v格式的 username=haha&password=123 SpringMVC的参数绑定过程是把表单提交的请求参数,作为控制器中方法的参数进行绑定的 要求 ...

  3. DaemonSet 典型应用场景【转】

    Deployment 部署的副本 Pod 会分布在各个 Node 上,每个 Node 都可能运行好几个副本.DaemonSet 的不同之处在于:每个 Node 上最多只能运行一个副本. DaemonS ...

  4. 将数据表中的数据添加到ComboBox控件中

    实现效果: 知识运用: ComboBox控件的DataSource 属性 //获取或设置ComboBox的数据源 public Object DataResouce{get;set;} //属性值:任 ...

  5. 解决sublime text 2总是在新窗口中打开文件(标签中打开)

    在mac下不是很喜欢sublime text 2 总是在新窗口中打开文件,很麻烦,文件打多了,就会出现N多窗口,虽然可以直接打开当前目录可以解决,但有时候查看其它项目中的单个文件,就比较麻烦.百度一直 ...

  6. USACO08FEB Hotel

    题目传送门 线段树维护区间 线段树结构体 struct zzz{ int l,r,mi; //l为以左端点的为起点的最长子串 //r为以右端点为终点的最长子串 //mi是区间内部的最长子串 }tree ...

  7. 零拷贝详解 Java NIO学习笔记四(零拷贝详解)

    转 https://blog.csdn.net/u013096088/article/details/79122671 Java NIO学习笔记四(零拷贝详解) 2018年01月21日 20:20:5 ...

  8. scipy学习之(二)——io操作及其misc操作对图片的处理

    SciPy有许多模块.类和函数,io子模块可用于从各种文件格式中读取数据和将数据写入各种文件格式. from scipy import io import numpy as np 生成数据 data ...

  9. php进行文件的强制下载

    浏览器下载文件,例如在浏览器中可以直接打开的文件(.gif /.txt等).在进行文件下载操作时,默认是通过浏览器直接打开,而不是下载保存文件.并且通过这种方法下载文件可以不暴漏下载文件所在的路径,可 ...

  10. VNC远程登录端使用经验之一

    1.vnc/xmanager都是经常用的远程登录软件.vnc有个缺点就是他的进程不会自动退出比如如果开了PID1再去开PID2...PIDn.那么前面的PIDn-1个进程就会一直运行如果不手动kill ...