洛谷ac通道!
一道非常良心卡空間的圖論題,比賽的時候我一交直接mle了。(然後才發現自己多按了個0)
題目中說要將所有的白點連向最近的黑點。在此之前,我們需要先將多餘的邊剔除掉 —— $m$居然是$n$的兩倍,這能不剔邊嗎!
怎麼剔呢?考慮增加乙個超級原點,編號 $n + 1$, 最開始向所有黑點連乙個$w = 0$的有向邊.
接著,我們從超級原點跑一次最短路 ($dyj$ 或者 $spfa$ 隨意), 然後我們就能得到一張最短路的圖 -> 然後按照這個圖建一張新的、精簡過的圖。 新邊連線要求: $dis_v == dis_u + w$ -> 這樣就能保證我們所連的邊都是盡量短的。
當然,在這裡要用到dfs來加邊。如果剛剛我們的超級原點加了無向邊,那麼在這裡會死迴圈,我們需要乙個 $vis$陣列來輔助。有向邊則不需要。
然後,在新圖上,如何保證連向最小的邊? 最小生成樹唄。 對新圖一波 $kruskal $ 就好了。
#include usingnamespace
std;
#define n 200100
#define ll long longinline
intread()
while
(isdigit(c))
return x *s;
}struct
node ;
node t[n
<< 2
];node e[n
<< 2
];int
f[n], head[n];
intn, m;
int bian = 0
;inline
void add(int u, int
v, ll w), f[u] =bian;
return;}
int bian2 = 0
;inline
void add1(int u, int
v, ll w), head[u] =bian2;
//e[++bian2] = (node), head[v] = bian2;
return;}
/*基本操作 end
*///
最短路 begin
struct
point
} ;ll d[n];
bool
vis[n];
priority_queue
q;#define v t[i].v
void dyj(int
s));
while(!q.empty()));}}
}}
return;}
//最短路 end
//最小生成樹 begin
void dfs(int now)
}return; }
#undef v
bool
cmp(node a, node b)
intfa[n];
int find(int
x)void
kruskal()
}if(ans == 0) printf("
impossible\n");
else printf("
%lld\n
", ans);
return;}
intmain()
for(int i = 1;i <= m; i++)
dyj(n + 1
); dfs(n + 1
); kruskal();
return0;
}
NOIP2015模擬10 22 最小代價
本來在比賽上就想到最小生成樹了,但不相信這道題那麼簡單,然後就沒有然後了。給出一幅由n個點m條邊構成的無向帶權圖。其中有些點是黑點,其他點是白點。現在每個白點都要與他距離最近的黑點通過最短路連線 如果有很多個黑點,可以選取其中任意乙個 我們想要使得花費的代價最小。請問這個最小代價是多少?注意 最後選...
NOIP2015模擬10 22 最大子矩陣
我們將矩陣a中位於第i行第j列的元素記作a i,j 乙個矩陣a是酷的僅當它滿足下面的條件 a 1,1 a r,s a 1,s a1 r,1 其中r為矩陣a的行數,s為矩陣a的列數。進一步,如果乙個矩陣是非常酷的僅當它的每乙個至少包含兩行兩列子矩陣都是酷的。你的任務是,求出乙個矩陣a中的乙個非常酷的子...
NOIP2015模擬11 5 旅行
經過觀察,可以發現題目有乙個比較不錯的性質 1 一條合法的路徑必須由兩條路徑組成,一條是奇數,另一條是偶數。所以我們可以先把每乙個點到達根節點的路徑求出來,深度為奇數的點放進乙個a aa陣列裡,偶數的放進b bb陣列裡,再給他們分別進行排序。然後進行兩兩結合,先把a陣列裡的所有數跟b1b b1 結合...