洛谷P4779
板子,堆优化+标记数组优化
spfa魔改
迪杰斯特拉堆优化+判断
zkw线段树优化
线段树优化
树状数组优化
左偏树优化,
左偏树+回收节点优化
小根堆优化
加一个zkw线段树优化的板子---虽然我看不懂= =
尝试了下洛谷里大佬说的几个Ac的方法
感觉都差不多
用时: 1487ms / 内存: 13272KB------------------------------------迪杰斯特拉堆优化+标记数组
用时: 1525ms / 内存: 12656KB------------------------------------魔改spfa(迪杰斯特拉+spfa的队列数组)
用时: 1501ms / 内存: 12960KB------------------------------------迪杰斯特拉堆优化+判断
第1,2个都需要额外开一个n的数组,3不需要
O2优化之后就都300ms左右了(话说手写堆的是真的强)
用时: 365ms / 内存: 13012KB
用时: 329ms / 内存: 12704KB
用时: 335ms / 内存: 13376KB
#include
using namespace std;
typedef long long ll;
vector > E[200005];
ll dis[100005];
bool vis[100005];
void init(ll n,ll m)
{
for(ll i=0;i<=n;i++)dis[i] = 1e18;
for(ll i=0;i<=m;i++)E[i].clear();
}
void dijstkra(ll s){
priority_queue > Q;
Q.push(make_pair(0,s));dis[s] = 0;
while(!Q.empty())
{
ll now = Q.top().second;
Q.pop();
if(vis[now])continue;
vis[now] = 1;
for(ll i=0;idis[now]+x)
{
dis[v] = dis[now]+x;
Q.push(make_pair(-dis[v],v));
}
}
}
}
int main() {
ll n,m,s;
while(~scanf("%lld%lld%lld",&n,&m,&s))
{
init(n,m);
for(ll i=0;i
void dijstkra(ll s){
priority_queue > Q;
Q.push(make_pair(0,s));dis[s] = 0;
while(!Q.empty())
{
ll now = Q.top().second;
Q.pop();
in[now] = 0;
for(ll i=0;idis[now]+x)
{
dis[v] = dis[now]+x;
if(!in[v])
Q.push(make_pair(-dis[v],v)),in[v] = 1;
}
}
}
}
void dijstkra(ll s){
priority_queue > Q;
Q.push(make_pair(0,s));dis[s] = 0;
while(!Q.empty())
{
ll now = Q.top().second;
ll t = -Q.top().first;
Q.pop();
if(t>dis[now])continue;
for(ll i=0;idis[now]+x)
{
dis[v] = dis[now]+x;
Q.push(make_pair(-dis[v],v));
}
}
}
}
#include
#define re register int
using namespace std;
const int N=1e5+5,M=5e5+5,inf=-1u>>1,oo=inf>>1;
typedef int arr[N];
struct edges{int nx,to,w;}e[M<<1];
int n,m,s,tot;arr fi,dis;
inline void add(re u,re v,re w){e[++tot]=(edges){fi[u],v,w};fi[u]=tot;}
namespace zkw{
int tr[N<<2],sgt=1;
inline void build(re n){while(sgt<=n)sgt<<=1;--sgt;tr[0]=N-1;}
inline void clr(){for(int i=1;i<=(sgt<<1)+1;i++)tr[i]=0;}
inline int cmp(const re&a,const re&b){return dis[a]w;i>>=1)tr[i]=x;dis[x]=w;}
inline void del(re x){tr[x+=sgt]=0;x>>=1;while(x)tr[x]=cmp(tr[x<<1],tr[x<<1|1]),x>>=1;}
}
using namespace zkw;
inline void dij(re s,re*dis){
for(int i=0;i<=n;i++)dis[i]=inf;clr();Mdy(s,0);
for(int k = 1;k<=n;k++){
re u=tr[1];del(u);
for(re i=fi[u],v;i;i=e[i].nx)
if(dis[v=e[i].to]>dis[u]+e[i].w)
Mdy(v,dis[u]+e[i].w);
}
}
int main(){
scanf("%d%d%d",&n,&m,&s);
build(n);re u,v,w;
for(int i=1;i<=m;i++)scanf("%d%d%d",&u,&v,&w),add(u,v,w);
dij(s,dis);
for(int i=1;i<=n;i++)
printf("%d%c",dis[i],i==n?'\n':' ');
return 0;
}
以下是写着玩的代码,自个儿乐一乐
自己写的
,开o2,600ms,不开1000ms
#include
using namespace std;
const int maxn=200000+100,inf = 0x3f3f3f3f;
typedef long long ll;
typedef pair,int> Edge;/// to,val,next
int dis[maxn],head[maxn],cnt,n,m,s;
Edge E[maxn];
bool vis[maxn];
void init(){memset(head,-1,sizeof(head)),cnt = 0;}
void add(int u,int v,int w){
E[cnt] = {{v,w},head[u]};
head[u] = cnt++;
}
struct node{
int l,r;
pair val;
}tree[maxn<<2];
void push_up(int x){
tree[x].val = min(tree[x<<1].val,tree[x<<1|1].val);
}
void build(int x,int l,int r){
tree[x].l = l,tree[x].r = r;
if(l == r)
tree[x].val = {dis[l],l};
else{
int mid = (l+r)>>1;
build(x<<1,l,mid);
build(x<<1|1,mid+1,r);
push_up(x);
}
}
void updata(int x,int pos,int val){
int L = tree[x].l,R = tree[x].r;
if(L == R && L == pos)
tree[x].val = {val,L};
else{
int mid = (L+R)>>1;
updata(pos<=mid?x<<1:x<<1|1,pos,val);
push_up(x);
}
}
pair query(int x,int l,int r){
int L = tree[x].l,R = tree[x].r;
if(l<=L && R<=r)
return tree[x].val;
else{
int mid = (L+R)>>1;
pair ans = {inf,inf};
if(l <= mid)ans = min(ans,query(x<<1,l,r));
if(r > mid )ans = min(ans,query(x<<1|1,l,r));
return ans;
}
}
void dijstkra(int s){
for(int i=1;i<=n;i++)dis[i] = inf;
dis[s] = 0;
build(1,1,n);
for(int k = 1;k<=n;k++){
int u = query(1,1,n).second;
vis[u] = 1;
updata(1,u,inf);
for(int i = head[u];~i;i = E[i].second)
if(!vis[E[i].first.first] && dis[E[i].first.first]>dis[u]+E[i].first.second)
updata(1,E[i].first.first,dis[u]+E[i].first.second),dis[E[i].first.first] = dis[u]+E[i].first.second;
}
}
int main(){
init();
scanf("%d%d%d",&n,&m,&s);
int u,v,w;
while(m--)scanf("%d%d%d",&u,&v,&w),add(u,v,w);
dijstkra(s);
for(int i=1;i<=n;i++)
printf("%d%c",dis[i],i==n?'\n':' ');
return 0;
}
复杂度多乘以个log也就是说复杂度是n*logn*longn,开o2,800ms,不开3000ms
#include
#define to first.first
#define W first.second
#define next second
using namespace std;
const int maxn=200000+100,inf = 0x3f3f3f3f;
typedef long long ll;
typedef pair,int> Edge;/// to,w,next
int head[maxn],cnt,n,m,s,ans[maxn];
pair dis[maxn],tree[maxn];
Edge E[maxn];
bool vis[maxn];
void init(){memset(head,-1,sizeof(head)),cnt = 0;}
void add(int u,int v,int w){
E[cnt] = make_pair(make_pair(v,w),head[u]);
head[u] = cnt++;
}
void updata(int pos){
while(pos<=n){
tree[pos] = dis[pos];
int lpos = pos&-pos;
for(int i=1;i query(int l,int r){
pair ans = {inf,inf};
while(r >= l){
ans = min(ans,dis[r--]);
while(r - (r&-r) >= l)
ans = min(ans,tree[r]),r -= r&-r;
}
return ans;
}
void dijstkra(int s){
for(int i=1;i<=n;i++)dis[i] = {inf,i},updata(i),ans[i]=inf;
dis[s] = {0,s},updata(s);
for(int k = 1;k<=n;k++){
int u = query(1,n).second;
ans[u] = dis[u].first;
vis[u] = 1;
dis[u].first = inf;
updata(u);
for(int i = head[u];~i;i = E[i].next)
if(!vis[E[i].to] && dis[E[i].to].first>ans[u]+E[i].W)
dis[E[i].to].first = ans[u]+E[i].W,updata(E[i].to);
}
}
int main(){
init();
scanf("%d%d%d",&n,&m,&s);
int u,v,w;
while(m--)scanf("%d%d%d",&u,&v,&w),add(u,v,w);
dijstkra(s);
for(int i=1;i<=n;i++)
printf("%d%c",ans[i],i==n?'\n':' ');
return 0;
}
笑,584ms,空间也是12MB,当然,看你开的数组大小了,不能自适应
#include
using namespace std;
typedef long long ll;
const int maxn = 1e5+7;
int head[maxn],to[maxn*4],wt[maxn*4],nex[maxn*4],cnt = 1;
ll ans[maxn];
int n,m,s;
void add(int u,int v,int w){
to[cnt] = v;
nex[cnt] = head[u];
wt [cnt] = w;
head[u] = cnt++;
}
int l[maxn*2],r[maxn*2],dis[maxn*2],tot,root;
pair val[maxn*2];
int Merge(int x,int y){
if(!x||!y)return x+y;
if(val[x]>val[y])swap(x,y);
r[x] = Merge(r[x],y);
if(dis[l[x]]ans[u])continue;
for(int i=head[u];i;i=nex[i]){
if(ans[to[i]]>ans[u]+wt[i]){
ans[to[i]] = ans[u]+wt[i];
val[++tot] = make_pair(ans[to[i]],to[i]);
root = Merge(tot,root);
}
}
}
}
int main() {
scanf("%d%d%d",&n,&m,&s);
while(m--){
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
add(u,v,w);
}
dijstkra(s);
for(int i=1;i<=n;i++)printf("%d%c",ans[i],i==n?'\n':' ');
return 0;
}
其实很简单,删掉的点就不用了,拿一个栈(数组模拟即可)存一下,
每次新加节点的时候看看栈空不空,不空就从栈里拿点就好
这样优化内存到了9MB左右,
#include
using namespace std;
typedef long long ll;
const int maxn = 1e5+7;
int head[maxn],to[maxn*4],wt[maxn*4],nex[maxn*4],stk[maxn],top,cnt = 1;
ll ans[maxn];
int n,m,s;
void add(int u,int v,int w){
to[cnt] = v;
nex[cnt] = head[u];
wt [cnt] = w;
head[u] = cnt++;
}
int l[maxn],r[maxn],dis[maxn],tot,root;
pair val[maxn];
int Merge(int x,int y){
if(!x||!y)return x+y;
if(val[x]>val[y])swap(x,y);
r[x] = Merge(r[x],y);
if(dis[l[x]] v){
if(top)
return val[stk[--top]] = v,stk[top];
return val[++tot] = v,tot;
}
void dijstkra(int s){
for(int i=1;i<=n;i++)ans[i] = 1e15;
ans[s] = 0;
root = Merge(root,push(make_pair(0,s)));
while(root){
int u = val[root].second;
ll w = val[root].first;
del();
if(w>ans[u])continue;
for(int i=head[u];i;i=nex[i]){
if(ans[to[i]]>ans[u]+wt[i]){
ans[to[i]] = ans[u]+wt[i];
root = Merge(root,push(make_pair(ans[to[i]],to[i])));
}
}
}
}
int main() {
scanf("%d%d%d",&n,&m,&s);
while(m--){
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
add(u,v,w);
}
dijstkra(s);
for(int i=1;i<=n;i++)printf("%lld%c",ans[i],i==n?'\n':' ');
//printf("%d\n",tot);
return 0;
}
(相当于手写优先队列)开o2 400ms,不开700ms
// luogu-judger-enable-o2
#include
using namespace std;
typedef long long ll;
vector > E[200005];
ll dis[100005];
bool vis[100005];
void init(ll n,ll m)
{
for(ll i=0;i<=n;i++)dis[i] = 1e18;
for(ll i=0;i<=m;i++)E[i].clear();
}
struct node{
ll pos,w;
}heap[100007<<4];
int tot;//small heap
void Insert(node data,int pos = tot+1){
heap[++tot] = data;
while(pos != 1 && heap[pos].w>1].w)
swap(heap[pos],heap[pos>>1]),pos>>=1;
}
void del(int pos = 1){
if(!tot)return;
heap[pos] = heap[tot--];
while(true){
int tpos = pos;
if((pos<<1)<=tot && heap[tpos].w>heap[pos<<1].w)tpos = pos<<1;
if((pos<<1|1)<=tot && heap[tpos].w>heap[pos<<1|1].w)tpos = pos<<1|1;
if(tpos == pos)break;
swap(heap[pos],heap[tpos]),pos = tpos;
}
}
void dijstkra(ll s){
Insert(node{s,0});
dis[s] = 0;
while(tot)
{
ll now = heap[1].pos;
del();
if(vis[now])continue;
vis[now] = 1;
for(ll i=0;idis[now]+x)
{
dis[v] = dis[now]+x;
Insert(node{v,dis[v]});
}
}
}
}
int main() {
ll n,m,s;
while(~scanf("%lld%lld%lld",&n,&m,&s))
{
init(n,m);
for(ll i=0;i