首页 > 代码库 > bzoj3669【NOI2014】魔法森林
bzoj3669【NOI2014】魔法森林
<style>pre.cjk { font-family: "Droid Sans Fallback", monospace }
p { margin-bottom: 0.25cm; line-height: 120% }</style>
喻队长的小常数代码,比某蒟蒻快一倍
题面
一道最短路好题……
开始和喻队长讨论了一下,喻队长一眼切:枚举ai的上界,
MAX每次把ai小于等于MAX的边加到图里,以bi为边权跑最短路。
但是,这样做是O(ai*m)的,妥妥TLE,于是我们想了一些鬼畜剪枝优化常数,然并卵……喻队长身先士卒(比喻队长带头,走在蒟蒻前面),交了一波,TLE60分。
后来,看了题解才发现这道题是SPFA的玄学用途——维护动态加边的图的最短路!只此一家,绝无仅有!于是我们就可以不用打LCT来维护一棵最小生成树。
具体做法其实很简单,每次距离数组不清零,只把新加入的边的两端点入队。这样的复杂度就是O(m)的了(也许吧,毕竟SPFA太玄学了),因为最后加起来相当于对原图跑一遍SPFA。
%%%%%%%%%%%%%%%喻队长
1 #include <algorithm>
2 #include <iostream>
3 #include <cstdlib>
4 #include <cstring>
5 #include <cstdio>
6 #include <cmath>
7 using namespace std;
8 const int N=50005,M=100005,INF=50005;
9 int gi(){
10 int str=0;char ch=getchar();
11 while(ch>‘9‘ || ch<‘0‘)ch=getchar();
12 while(ch>=‘0‘ && ch<=‘9‘)str=(str<<1)+(str<<3)+ch-48,ch=getchar();
13 return str;
14 }
15 int n,m;
16 struct node{
17 int x,y,dis,dist;
18 bool operator <(const node &pp)const{
19 return dis<pp.dis;
20 }
21 }e[M];
22 int head[N],num=0;
23 struct Lin{
24 int next,to,dis;
25 }a[M<<1];
26 void init(int x,int y,int z){
27 a[++num].next=head[x];
28 a[num].to=y;a[num].dis=z;
29 head[x]=num;
30 }
31 void addedge(int x,int y,int z){
32 init(x,y,z);init(y,x,z);
33 }
34 int t=0,sum=0,q[N*10],mod=N*10,f[N],ans=(INF<<1);bool vis[N],usd[M];
35 bool spfa(int lim){
36 int x,u,tmp;
37 while(t!=sum){
38 t++;if(t==mod)t-=mod;x=q[t];
39 for(int i=head[x];i;i=a[i].next){
40 u=a[i].to;tmp=a[i].dis>f[x]?a[i].dis:f[x];
41 if(tmp<f[u]){
42 f[u]=tmp;
43 if(!vis[u]){
44 vis[u]=true;
45 sum++;if(sum==mod)sum-=mod;q[sum]=u;
46 }
47 }
48 }
49 vis[x]=false;
50 }
51 if(f[n]==INF)return false;
52 ans=min(ans,f[n]+lim);
53 return true;
54 }
55 void build(int sta){
56 t=0;sum=0;
57 for(int i=sta;i<=m && e[i].dis==e[sta].dis;i++){
58 addedge(e[i].x,e[i].y,e[i].dist);
59 q[++sum]=e[i].x;q[++sum]=e[i].y;
60 vis[e[i].x]=true;vis[e[i].y]=true;
61 usd[i]=true;
62 }
63 }
64 void work(){
65 n=gi();m=gi();
66 for(int i=1;i<=m;i++)
67 e[i].x=gi(),e[i].y=gi(),e[i].dis=gi(),e[i].dist=gi();
68 sort(e+1,e+m+1);
69 int limiter=e[m].dis;
70 memset(f,127/3,sizeof(f));
71 f[1]=0;
72 for(int i=1;i<=m;i++){
73 if(usd[i])continue;
74 build(i);
75 spfa(e[i].dis);
76 }
77 if(ans==(INF<<1))printf("-1\n");
78 else printf("%d\n",ans);
79 }
80 int main()
81 {
82 work();
83 return 0;
84 }
bzoj3669【NOI2014】魔法森林
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。