[USACO Jan09] 安全路径

本文介绍了一种解决农场牛群避开Gremlins寻找最短路径的问题,利用Dijkstra算法和左偏树实现路径规划,确保每头牛都能找到一条不经过特定障碍物的最短路径。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Gremlins最近在农场上泛滥,它们经常会阻止牛们从农庄(牛棚_1)走到别的牛棚(牛_i的目的
地是牛棚_i).每一个gremlin只认识牛_i并且知道牛_i一般走到牛棚_i的最短路经.所以它
们在牛_i到牛棚_i之前的最后一条牛路上等牛_i. 当然,牛不愿意遇到Gremlins,所以准备找
一条稍微不同的路经从牛棚_1走到牛棚_i.所以,请你为每一头牛_i找出避免gremlin_i的最
短路经的长度.

和以往一样, 农场上的M (2 <= M <= 200,000)条双向牛路编号为1..M并且能让所有牛到
达它们的目的地, N(3 <= N <= 100,000)个编号为1..N的牛棚.牛路i连接牛棚a_i
(1 <= a_i <= N)和b_i (1 <= b_i <= N)并且需要时间t_i (1 <=t_i <= 1,000)通过.
没有两条牛路连接同样的牛棚,所有牛路满足a_i!=b_i.在所有数据中,牛_i使用的牛棚_1到牛
棚_i的最短路经是唯一的.

以下是一个牛棚,牛路和时间的例子:

      1--[2]--2-------+
      |       |       |
     [2]     [1]     [3]
      |       |       |
      +-------3--[4]--4

   行程         最佳路经      最佳时间     最后牛路
p_1 到 p_2       1->2          2         1->2
p_1 到 p_3       1->3          2         1->3
p_1 到 p_4      1->2->4        5         2->4

当gremlins进入农场后:

   行程         最佳路经      最佳时间      避免
p_1 到 p_2     1->3->2         3         1->2
p_1 到 p_3     1->2->3         3         1->3
p_1 到 p_4     1->3->4         6         2->4

20%的数据满足N<=200.

50%的数据满足N<=3000.

时间限制: 3秒

内存限制: 64 MB

PROBLEM NAME: travel

输入格式:

* 第一行: 两个空格分开的数, N和M

* 第2..M+1行: 三个空格分开的数a_i, b_i,和t_i

样例输入 (travel.in):

4 5
1 2 2
1 3 2
3 4 4
3 2 1
2 4 3

输入解释:

跟题中例子相同

输出格式:

* 第1..N-1行: 第i行包含一个数:从牛棚_1到牛棚_i+1并且避免从牛棚1到牛棚i+1最
短路经上最后一条牛路的最少的时间.如果这样的路经不存在,输出-1.

样例输出 (travel.out):

3
3
6


题解:
好题珍藏
由于最短路径唯一,那么可以把到1的最短路径连起来,形成最短路树(本蒟蒻这不懂套路)
然后我们根据题意知道,1-x的路径中,不能走的为x的父亲边,那么我们就设法绕开这条边
于是想到合法情况:从1开始先绕到非x的子树上的一个节点u,再通过该节点绕道x子树上一个节点p再从p到x
答案即为f[u]+dis(u,p)+f[p]-f[x]
那么想到用堆维护f[u]+dis(u,p)+f[p] 然后用左偏树合并,并用并查集判断是否在x的子树内即可
  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <algorithm>
  5 #include <cmath>
  6 #include <queue>
  7 #include <vector>
  8 using namespace std;
  9 const int N=100005,M=200005,inf=2e9;
 10 int head[N],num=0;
 11 struct Lin{
 12     int next,to,dis;
 13 }a[M<<1],e[M<<1];
 14 void init(int x,int y,int dis){
 15     a[++num].next=head[x];a[num].to=y;a[num].dis=dis;head[x]=num;
 16 }
 17 int n,m;
 18 int gi(){
 19     int str=0;char ch=getchar();
 20     while(ch>'9' || ch<'0')ch=getchar();
 21     while(ch>='0' && ch<='9')str=(str<<1)+(str<<3)+ch-48,ch=getchar();
 22     return str;
 23 }
 24 struct pr{
 25     int id,dis;
 26     bool operator <(const pr &pp)const{
 27         return dis>pp.dis;
 28     }
 29 };
 30 priority_queue<pr>q;
 31 bool vis[N];int f[N],pre[N];
 32 void dj(){
 33     int cnt=0,x,u,dis;
 34     for(int i=1;i<=n;i++)f[i]=inf;
 35     q.push((pr){1,0});f[1]=0;
 36     while(!q.empty()){
 37         x=q.top().id;dis=q.top().dis;q.pop();
 38         if(vis[x] || f[x]!=dis)continue;
 39         cnt++;vis[x]=true;if(cnt==n)break;
 40         for(int i=head[x];i;i=a[i].next){
 41             u=a[i].to;
 42             if(f[x]+a[i].dis<f[u])f[u]=f[x]+a[i].dis,pre[u]=x;
 43             q.push((pr){u,f[u]});
 44         }
 45     }
 46 }
 47 int fa[N],ans[N];
 48 int find(int x){
 49     return fa[x]==x?x:fa[x]=find(fa[x]);
 50 }
 51 struct node{
 52     int val,dis,id;
 53     node *l,*r;
 54     int ldis(){return l?l->dis:0;}
 55     int rdis(){return r?r->dis:0;}
 56 }T[N*10];
 57 node *root[N],*pos=T;
 58 node *merge(node *p,node *q){
 59     if(!p || !q)return p?p:q;
 60     if(p->val>q->val)swap(p,q);
 61     p->r=merge(p->r,q);
 62     if(p->ldis()<p->rdis())swap(p->l,p->r);
 63     p->dis=p->rdis()+1;
 64     return p;
 65 }
 66 void delet(int x){
 67     root[x]=merge(root[x]->r,root[x]->l);
 68 }
 69 void dfs(int x,int last){
 70     int u;
 71     fa[x]=x;
 72     for(int i=head[x];i;i=a[i].next){
 73         u=a[i].to;if(u==last)continue;
 74         if(f[x]+a[i].dis==f[u]){
 75             dfs(u,x);
 76             fa[find(u)]=find(x);
 77             root[x]=merge(root[x],root[u]);
 78         }
 79     }
 80     node *tmp;
 81     for(int i=head[x];i;i=a[i].next){
 82         u=a[i].to;
 83         if(u==last || find(u)==find(x))continue;
 84         tmp=pos++;tmp->l=NULL;tmp->r=NULL;tmp->val=f[u]+a[i].dis+f[x];tmp->id=u;
 85         root[x]=merge(root[x],tmp);
 86     }
 87     while(root[x] && find(root[x]->id)==find(x))delet(x);
 88     if(root[x])ans[x]=root[x]->val-f[x];
 89     else ans[x]=-1;
 90 }
 91 void work()
 92 {
 93     int x,y,z;
 94     n=gi();m=gi();
 95     for(int i=1;i<=m;i++){
 96         x=gi();y=gi();z=gi();
 97         init(x,y,z);init(y,x,z);
 98     }
 99     dj();dfs(1,1);
100     for(int i=2;i<=n;i++)printf("%d\n",ans[i]);
101 }
102 int main()
103 {
104     freopen("travel.in","r",stdin);
105     freopen("travel.out","w",stdout);
106     work();
107 }

 

 

转载于:https://www.cnblogs.com/Yuzao/p/7224289.html

### USACO 2016 January Contest Subsequences Summing to Sevens Problem Solution and Explanation In this problem from the USACO contest, one is tasked with finding the size of the largest contiguous subsequence where the sum of elements (IDs) within that subsequence is divisible by seven. The input consists of an array representing cow IDs, and the goal is to determine how many cows are part of the longest sequence meeting these criteria; if no valid sequences exist, zero should be returned. To solve this challenge efficiently without checking all possible subsequences explicitly—which would lead to poor performance—a more sophisticated approach using prefix sums modulo 7 can be applied[^1]. By maintaining a record of seen remainders when dividing cumulative totals up until each point in the list by 7 along with their earliest occurrence index, it becomes feasible to identify qualifying segments quickly whenever another instance of any remainder reappears later on during iteration through the dataset[^2]. For implementation purposes: - Initialize variables `max_length` set initially at 0 for tracking maximum length found so far. - Use dictionary or similar structure named `remainder_positions`, starting off only knowing position `-1` maps to remainder `0`. - Iterate over given numbers while updating current_sum % 7 as you go. - Check whether updated value already exists inside your tracker (`remainder_positions`). If yes, compare distance between now versus stored location against max_length variable's content—update accordingly if greater than previous best result noted down previously. - Finally add entry into mapping table linking latest encountered modulus outcome back towards its corresponding spot within enumeration process just completed successfully after loop ends normally. Below shows Python code implementing described logic effectively handling edge cases gracefully too: ```python def find_largest_subsequence_divisible_by_seven(cow_ids): max_length = 0 remainder_positions = {0: -1} current_sum = 0 for i, id_value in enumerate(cow_ids): current_sum += id_value mod_result = current_sum % 7 if mod_result not in remainder_positions: remainder_positions[mod_result] = i else: start_index = remainder_positions[mod_result] segment_size = i - start_index if segment_size > max_length: max_length = segment_size return max_length ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值