Kruskal
struct Edge
{
int s,e;///s记录起点,e记录终点
double dis;///dis记录起点到终点的距离
}e[5555];
int cmp(Edge a,Edge b)
{
return a.dis < b.dis;///按距离从小到大排列
}
int father(int x)///找父亲节点,用于判断是否在一个集合中
{
if(x == fa[x]) return x;
else
{
int root = father(fa[x]);
fa[x] = root;
return root;
}
}
int Kruskal()
{
for(int i = 1; i <= n; i++)
fa[i] = i;
sort(e,e+cunt,cmp);///按从小到大对所有边进行排序
double ans = 0;
for(int i = 0; i < cunt; i++)///遍历所有的边
{
int a = father(e[i].s);
int b = father(e[i].e);
if(a != b)
{
ans += e[i].dis;
fa[a] = b;///合并集合
}
}
return ans;///返回最小生成树的权值和
}
Prime
int Prime(int v)///最小生成树的起点v
{
sum = 0;
for(int i = 1; i <= n; i++)
d[i] = dis[v][i];
d[v] = 0;
flag[v] = 1;///flag用来标记是否遍历过
for(int i = 1; i < n; i++)///一共n个点,要找n-1条边
{
int minn = INF,k;
for(int j = 1; j <= n; j++)///在所有u∈U,w∈V-U的边(u,w)∈E中找到一条权值最小的边
{
if(minn > d[j] && flag[j] == 0)
{
k = j;
minn = d[j];
}
}
flag[k] = 1;///将此点加入最小生成树中
sum += d[k];
for(int j =1; j <= n; j++)///更新不在最小生成树的点的边权值,以便找到下一个权值最小的边
{
if(flag[j] == 0 && d[j] > dis[k][j])
d[j] = dis[k][j];
}
}
return sum;///返回生成的最小生成树的权值和
}
Bellman-ford
int N, M;
typedef struct node
{
int u, v;
int cost;
} E;
node E[N];
int dis[N], pre[N];
bool Bellman()
{
int ok;
for(int i = 1; i <= N; ++i)
dis[i] = (i == 1 ? 0 : MAX);
for(int i = 1; i <= N - 1; ++i)
{
ok=1;
for(int j = 1; j <= M; ++j)
if(dis[E[j].v] > dis[E[j].u] + E[j].cost)
{
dis[E[j].v] = dis[E[j].u] + E[j].cost;
ok=0;
}
if(ok==1)
break;
}
bool flag = 1;
for(int i = 1; i <= M; ++i)
if(dis[E[i].v] > dis[E[i].u] + E[i].cost)
{
flag = 0;
break;
}
return flag;
}
int main()
{
cin>>N>>M;
for(int i = 1; i <= M; ++i)
cin>>E[i].u>>E[i].v>>E[i].cost;
if(Bellman())
cout<<dis[M];
else
cout<<"存在负";
return 0;
}
并查集
int father(int x)///找父亲节点,用于判断是否在一个集合中
{
if(x == fa[x]) return x;
else return fa[x]= father(fa[x]);
}