USACO 2015 January S 题解
2015 January S
P3114 [USACO15JAN]Stampede S
本题和区间覆盖有点类似,每头牛所对应的区间就是这头牛能被看到的时间
区间以 \(y\)? 坐标进行降序排序,直接区间覆盖即可
注意,本题必须用左闭右开区间存储,因为在结束的那一刻是看不见的(已经离开了)
为了存储这些区间,我们采用离散化的方式存储(主要是离散化后可以暴力覆盖)
代码:
#include
P3115 [USACO15JAN]Cow Routing S
对每条航线进行建边处理,同时记录两个城市之间的城市数,然后跑最短路即可
注意,本题由于边数比较多,建议用邻接矩阵存储
代码:
#include
#include
#include
typedef long long ll;
using namespace std;
const ll inf_ll=1e16;
const int inf_int=0x3f3f3f3f;
const int N=1e3+7;
struct node {
ll w;
int num,u;
inline bool operator < (const node &y) const {
return w>y.w || (w==y.w && num>y.num);
}
};
vector plane;
pair edge[N][N];
ll dis[N];
int pre[N];
int s,e,n;
inline void Dijkstra(int s) {
priority_queue q;
for(int i=1;idis[u]+w || (dis[v]==dis[u]+w && pre[v]>pre[u]+num) ) {
dis[v]=dis[u]+w;
pre[v]=pre[u]+num;
q.push({dis[v],pre[v],v});
}
}
}
}
signed main() {
scanf("%d%d%d",&s,&e,&n);
for(int i=1;iprice)
edge[u][v]={price,plane.size()-j}; // 当前点到 u 经过这条航线要经过 plane.size()-j 个点
else if(edge[u][v].first==price && edge[u][v].second>plane.size()-j)
edge[u][v]={price,plane.size()-j};
}
plane.push_back(v);
}
}
Dijkstra(s);
if(pre[e]==-1)
puts("-1 -1");
else
printf("%lld %d",dis[e],pre[e]);
return 0;
}
P3116 [USACO15JAN]Meeting Time S
先考虑暴力
设 \(b_{i,j}\)? 为 \(\tt{Bessie}\)?? 能否用 \(j\) 的使时间到达第 \(i\)?? 个点, \(e_{i,j}\)??? 为 \(\tt{Elesie}\)???? 能否用 \(j\)?? 的使时间到达第 \(i\)??? 个点
我们通过广搜遍历每一个点(此题为有向无环图),状态转移方程为:
\[b_{v,i+w1}|=b_{u,i} \\ e_{v,i+w2}|=e_{u,i} \]可以拿到部分分数
考虑优化,暴力的主要缺点是转移完时候可能还有路径到达这个点,造成多次计算
那我们可不可以先把所有可以到达这个点的路径全部遍历完再转移,显然,我们可以用拓扑排序实现
代码如下:
#include
#include
#include
using namespace std;
const int N=1e2+7;
struct node {
int v,w1,w2;
};
vector edge[N];
queue q;
bool bessie[N][N*N],elsie[N][N*N];
int indeg[N];
int n,m;
inline void TopoSort() {
bessie[1][0]=elsie[1][0]=true;
for(int i=1;i<=n;++i)
if(!indeg[i])
q.push(i);
while(!q.empty()) {
int u=q.front();
q.pop();
for(int i=0,v,w1,w2;i