最短路徑、最小生成樹
DP想法!!
int dis[MAXN];
vector<pair<int,int>> graph[MAXN];
void dijkstra_algorithm(int start,int end){
priority_queue<pair<int,int>,vector<pair<int,int>>,greater<pair<int,int>>> pq;
bool visited[n+1] = {false};
for(int i=1;i<=n;i++) dis[i] = INF;
dis[start] = 0;
pq.push({0,start});
while(pq.size()){
auto [w,v] = pq.top();
pq.pop();
if(visited[v]) continue;
visited[v] = 1;
for(auto [w_2,v_2]:graph[v]){
if(w+w_2<dis[v_2]){//relaxation
dis[v_2] = w+w_2;
pq.push({dis[v_2],v_2});
}
}
}
}
dijkstra不能處理負邊!
int dis[MAXN][MAXN];
void Floyd_Warshall(int start,int end){
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
for(int k=1;k<=n;k++){
dis[i][j] = min(dis[i][j],dis[i][k]+dis[k][j]);
}
}
}
}
兩條紅線 你要選哪個來連接兩個MST?
const int MAXN = (int)2e5;
int dsu[MAXN]; //第i項表示i點的父節點
void Init(){
for (int i=0;i<MAXN;i++) dsu[i] = i;
}
//先將每項的父元素設為本身
int query(int k){
if (k==dsu[k]) return k;
dsu[k] = query(dsu[k]);//老大的老大就是我的老大
return dsu[k];
}
void modify (int x,int y){
int xA = query(x);
int yA = query(y);
if (xA!=yA) dsu[xA] = yA;
}
簡單的DSU題目練習:CF445B
struct road{
ll f;
ll s;
ll val;
};
int dsu[MAXN];
vector<road> graph;
int find(int x){
return dsu[x] == x ? x : dsu[x] = find(dsu[x]);
}
void modify(int x,int y){
int pa = find(x);
int pb = find(y);
if(pa!=pb) dsu[pb] = pa;
}
void solve(){
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++) dsu[i] = i;
while(m--){
road r;
cin>>r.f>>r.s>>r.val;
graph.pb(r);
}
ll sum = 0;
sort(all(graph),[](road a,road b){return a.val<b.val;});
for(auto [a,b,c]:graph){
if(find(a)!=find(b)){
sum+=c;
modify(a,b);
}
}
cout<<sum<<endl;
return;
}
提示:
邊權為0,1的圖,如果能做出權重\(a,b(a<b)\)的生成樹,則可以做出\([a,b]\)權重的生成樹。