題解 GXOI GZOI2019 旅行者

2022-05-01 20:54:08 字數 1485 閱讀 5060

調這個題調了兩個月,被自己蠢哭

給乙個有向圖,一組關鍵點,求關鍵點之間的最短的距離

這個題目有兩種做法,分別是 $nlogn$ 和 $nlog^2n$ 的

首先說 $nlogn$ 的官方做法,我們考慮多源迪傑斯特拉

正圖上從 k 個關鍵點出發跑 $dijkstra$,記某個點離最近的關鍵點距離為 $dis[0][i]$

反圖上也從 k 個關鍵點出發跑 $dijkstra$,距離記為 $dis[1][i]$

列舉正圖中的邊 $u->v: w$, 用 $dis[0][u]+dis[1][v]+w$ 更新答案

然後就是一種很好打的 $nlognlogk$ 的做法,我們考慮一種思想,二進位制分組

對於每乙個在集合中的元素,我們進行重新標號,然後對每一位進行$0/1$二進位制分組,由於每個元素的編號不一樣,所以至少有一位的分組不同,然後一組連 $s$,一組連 $t$,這樣跑 $logk$ 組的從 $s$ 到 $t$ 的最短路,去 $min$,即可

#include using namespace std;

#define re register

#define ll long long

#define gc getchar()

inline int read()

const int n=5e5+10,m=1e6+10;

ll inf=1e15+7;

int h[n],n,m,cnt,k,a[n],x[n],y[n],z[n],s,t;

struct node e[m<<1];

ll dis[n],ans=inf;

void add(int u,int v,int w),h[u]=cnt;}

#define qxx(u) for(int i=h[u],v;v=e[i].to,i;i=e[i].next)

struct node

};priority_queueq;

void dijkstra()

); while(!q.empty()));}

}} void work()

for(int i=1;i<=m;++i)

add(x[i],y[i],z[i]);

dijkstra();

ans=min(ans,dis[t]);

memset(h,0,sizeof(h));

cnt=0;

for(int i=1;i<=k;++i)

for(int i=1;i<=m;++i)

add(y[i],x[i],z[i]);

dijkstra();

ans=min(ans,dis[t]);

}cout<

}int main()

GXOI GZOI2019 逼死強迫症

傳送門 to luogu 將道路看成乙個很高很瘦的傢伙 乙個 n 2 n times 2 n 2 的瘦高個 考慮最後一行 或者說,第一行 是什麼情況。用 f n f n f n 表示答案。不好搞定的是第三種情況。下面都只討論第三種情況。如圖。不妨設第一行的 1 1 1 times 1 1 1 磚塊在...

GXOI GZOI2019 舊詞 解題報告

對於一棵 n 個節點的樹,給出 m 次詢問和常數 k 每次給出 r,x 求 sum limits r depth lca i,x k n,m le 5 times 10 4 1 le r,x le n k le 10 9 如果有做過 lnoi2014 lca,就很容易想出解法。可以通過樹上差分,點 ...

GXOI GZOI2019 旅行者 (最短路)

給定乙個有向圖,其中一些頂點為關鍵點。求這些關鍵點兩兩之間最小距離。考試時沒怎麼想寫了50分暴力走了。以為是什麼強連通分量的解法,結果就是個最短路。直接從關鍵點跑一次最短路dis 0 再把圖反向在跑一次最短路dis 1 跑最短路的時候記錄起點col 0 1 那麼最後直接列舉一條邊 x,y,w 當co...