最小生成树
//prim 算法
#include<iostream>
#include<string.h>
using namespace std;
int mp[3003][3003];
int vis[3003],d[3003];
int n,m;
void prim(){
memset(d,0x3f,sizeof d);
memset(vis,0,sizeof vis);
d[1] = 0;
for(int i=1;i<n;i++){
int x = 0;
for(int j=1;j<=n;j++){
if(!vis[j] && d[j] < d[x]) x = j;
}
vis[x] = 1;
for(int j=1;j<=n;j++){
if(!vis[j]){
d[j] = min(mp[j][x],d[j]);
}
}
}
}
int main(){
memset(mp,0x3f,sizeof mp);
int ans = 0,cnt = 0;
cin >> n >> m;
for(int i=1;i<=n;i++){
mp[i][i] = 0;
}
for(int i=1;i<=m;i++){
int u,v,w;
cin >> u >> v >> w;
mp[u][v] = mp[v][u] = min(mp[u][v],w);
}
prim();
for(int i=2;i<=n;i++){
if(d[i]){
cnt++;
if(ans < d[i]){
ans = d[i];
}
}
}
cout << cnt << " " << ans;
}
//kruscal算法
//1.并查集写 其实书上也是用到了并查集没明说而已
#include<iostream>
#include<string.h>
#include<algorithm>
using namespace std;
const int maxn = 1e5+5;
struct Edge{
int u,v,w;
bool operator < (const Edge & e)const{
return w < e.w; // 重载< 运算符
}
}e[maxn];//内存绝对够
int fa[maxn]; // 判断是不是在一个连通分量
int find(int x){
if(fa[x] != x) fa[x] = find(fa[x]); // 路径压缩
return fa[x];
}
void merge(int a,int b){
int x = find(a); int y = find(b);
fa[x] = y;
}
int main(){
int n,m;
int ans = 0 , cnt = 0;
cin >> n >> m;
for(int i=1;i<=n;i++){
fa[i] = i ; // 预处理下
}
for(int i=1;i<=m;i++){
int u,v,w;
cin >> u >> v >> w;
e[i].u = u, e[i].v = v,e[i].w = w;
}
sort(e+1,e+1+m) ;// 也可以用冒泡排序这里就不多写了
for(int i=1;i<=m;i++){
int u = e[i].u;
int v = e[i].v;
if(find(u) != find(v)){
merge(u,v);
cnt++;
ans = e[i].w;
}
}
cout << cnt << " " << ans ;
}
//dfs判断环
#include<iostream>
#include<string.h>
#include<algorithm>
#include<vector>
using namespace std;
const int maxn = 1e5 + 5;
int n, m;
int vis[maxn]; // 判断有没有被选
int vis2[maxn];
int ans = 0, cnt = 0,flag = 0;
vector<int>son[maxn];
struct Edge {
int u, v, w;
bool operator < (const Edge & e)const {
return w < e.w; // 重载< 运算符
}
} e[maxn]; //内存绝对够
void dfs(int u,int v1){
for(int i=0;i<son[u].size();i++){
int v = son[u][i];
if(vis2[v]) continue;
vis2[v] = 1;
if(vis[v]){
if(v == v1){
flag = 1;
return;
}
else if(!flag){
dfs(v,v1);
}
}
}
}
void kruscal() {
for(int i=1;i<=m;i++){
int u = e[i].u;
int v = e[i].v;
memset(vis2,0,sizeof vis2);
dfs(u,v);
if(!flag && (!vis[u]||!vis[v])){
vis[u] = vis[v] = 1;
cnt++;
ans = e[i].w;
}
flag = 0;
}
}
int main() {
memset(vis, 0, sizeof vis);
cin >> n >> m;
for (int i = 1; i <= m; i++) {
int u, v, w;
cin >> u >> v >> w;
son[u].push_back(v);
son[v].push_back(u);
e[i].u = u, e[i].v = v, e[i].w = w;
}
sort(e + 1, e + 1 + m) ; // 也可以用冒泡排序这里就不多写了
kruscal();
cout << cnt << " " << ans;
}
//1.普通dijstra算法
#include<iostream>
#include<string.h>
#include<vector>
using namespace std;
const int maxn = 1e6 + 5;
struct Edge{
int to,next,w;
};
Edge edge[maxn];
int d[maxn];
int vis[maxn], cnt = 0;
int n, m,head[maxn];
void add(int u,int v,int w){
edge[++cnt].to = v;
edge[cnt].next = head[u];
edge[cnt].w = w;
head[u] = cnt;
}
void dijstra() {
for (int i = 1; i <= n - 1; i++) {
int x = 0;
for(int j = 1; j <= n; j++)
if(!vis[j] && (x == 0 || (d[x] > d[j]))) x= j;
vis[x] = 1;
for(int i=head[x];i;i=edge[i].next){
int v = edge[i].to;
d[v] = min(d[v],d[x] + edge[i].w);
}
}
}
int main() {
memset(d, 0x3f, sizeof(d));
memset(vis, 0, sizeof(vis));
cin >> n >> m;
for (int i = 1; i <= m; i++) {
int u, v, w;
cin >> u >> v >> w;
add(u,v,w);
add(v,u,w);
}
d[1] = 0;
dijstra();
cout << d[n];
}
//2.堆优化的dijstra算法
#include<iostream>
using namespace std;
#include<queue>
#include<vector>
#include<algorithm>
#include<string.h>
const int maxn = 1e4+5;
int d[maxn],vis[maxn];
struct edge{
int v;
int w;
};
vector<edge> son[maxn];
struct node{
int dis,u;
};
bool operator > (const node &a,const node& b) {
return a.dis > b.dis;
}
priority_queue<node,vector<node>,greater<node>> q;
void dijstra(int s){
d[s] = 0;
vis[s] = 0;
q.push({0,s});
while(!q.empty()){
node t = q.top();
q.pop();
int u = t.u;
if(vis[u]){
continue;
}
for(int i=0;i<son[u].size();i++){
int v = son[u][i].v;
int w = son[u][i].w;
if(d[v] > d[u] + w){
d[v] = d[u] + w;
q.push({d[v],v});
}
}
}
}
int main(){
int n,m;
cin >> n >> m;
for(int i=1;i<=m;i++){
int u,v,w;
cin >> u >> v >> w;
son[u].push_back({v,w});
son[v].push_back({u,w});
}
memset(d,63,sizeof(d));
memset(vis,0,sizeof(vis));
dijstra(1);
cout << d[n] ;
}
//3.spfa算法
//队列写法
#include<iostream>
using namespace std;
#include<queue>
#include<string.h>
const int maxn = 1e6+5;
struct Edge{
int to,next,w;
};
Edge edge[maxn];
int vis[maxn],n,m,d[maxn],cnt = 0;
int head[maxn];
queue<int> q;
void add(int u,int v,int w){
edge[++cnt].to = v;
edge[cnt].next = head[u];
edge[cnt].w = w;
head[u] = cnt;
}
void spfa(){
memset(vis,0,sizeof(vis));
memset(d,0x3f,sizeof(d));
d[1] = 0;
vis[1] = 1;
q.push(1);
while(!q.empty()){
int u = q.front();
q.pop();
vis[u] = 0;
for(int i=head[u];i;i = edge[i].next){
int v = edge[i].to;
if( d[v] > d[u] + edge[i].w ){
d[v] = d[u] + edge[i].w;
if(!vis[v]) q.push(v);
}
}
}
}
int main(){
cin >> n >> m;
for(int i=1;i<=m;i++){
int u,v,w;
cin >> u >> v >> w;
add(u,v,w);
add(v,u,w);
}
spfa();
cout << d[n];
}
//4.floyd算法 只是费时间而已
#include<iostream>
#include<string.h>
using namespace std;
int d[1000][1000];
int n,m;
int main(){
cin >> n >> m;
memset(d,0x3f,sizeof(d));
for(int i=1;i<=n;i++){
d[i][i] = 0;
}
for(int i=1;i<=m;i++){
int u,v,w;
scanf("%d %d %d",&u,&v,&w);
d[u][v] = min(d[u][v],w);
}
for(int k=1;k<=n;k++){
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
d[i][j] = min(d[i][j],d[i][k] + d[k][j]);
}
}
}
cout << d[1][n];
}