Floyd多源
优点:多源时高效,好打,多源,可负权,稠密图效果更好。
缺点:时间复杂度比较高,不适合计算大量数据。
const int inf = 0x3f3f3f3f;
int g[MAX_N][MAX_N]; // 算法中的 G 矩阵
// 初始化 g 矩阵
void init() {
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
if (i == j) {
g[i][j] = 0;
} else {
g[i][j] = inf;
}
}
}
}
// 插入一条带权有向边
void insert(int u, int v, int w) {
g[u][v] = w;
}
// 核心代码
void floyd() {
for (int k = 0; k < n; ++k) {
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
if (g[i][k] + g[k][j] < g[i][j]) {
g[i][j] = g[i][k] + g[k][j];
}
}
}
}
}
主要就是一个“找转接点”的思想来求最短路。需要根据题意灵活变通。
例题 蒜头年会:
大致思路:
把关系想象成图,员工之间亲密度要取可能亲密度之中的最小值——则要用floyd求多源最短路。
赋权值
要注意一个项目之中的每个员工之间都要建立关系(亲密度=1),且根据题意亲密度不叠加。
而且,联系实际,自己和自己不应该有什么亲密度一说,所以在最后关键步骤那里注意 i!=j !!!
代码:
#include<iostream>
#include<bits/stdc++.h>
using namespace std;
const int MAXN=305;
int g[MAXN][MAXN];
const int INF=0x3f3f3f3f;
void init()
{
memset(g,0x3f,sizeof(g));
}
int main()
{
init();
int n,m;
cin>>n>>m;
while(m--)
{
int nn;
scanf("%d",&nn);
int d1[nn];
int d2[nn];
for(int i=0;i<nn;i++)
{
cin>>d1[i];
d2[i]=d1[i];
}
for(int i=0;i<nn;i++)
{
for(int j=0;j<nn;j++)
{
if(i!=j)
{
g[d1[i]][d2[j]]=1; //根据题意,只要在同一项目中工作过则亲密度为1,不叠加。
}
}
}
}
for(int k=1;k<=n;k++)
{
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(i!=j && g[i][k]+g[k][j]<g[i][j]) //注意i!=j
g[i][j]=g[i][k]+g[k][j];
}
}
}
double minn=INF;
for(int i=1;i<=n;i++)
{
double sum=0;
for(int j=1;j<=n;j++)
{
if(i!=j)
{
sum+=g[i][j];
}
}
sum=sum/(n-1); //不用算自己 (细节注意)
minn=min(sum,minn);
}
cout<<(int)(minn*100);
return 0;
}
例题:美丽的邂逅
思路:
模板题。主要还是注意“自己和自己不用去找隔了几个人 i!=j”,建图,每个边权值都=1,然后根据题意,最后遍历每两个点间的最短路若>7(可画图,如果两个点之间隔了6个点,则隔了7条边,路径长度为7)则结论不成立。
#include<iostream>
#include<bits/stdc++.h>
using namespace std;
const int MAXN=305;
int g[MAXN][MAXN];
const int INF=0x3f3f3f3f;
void init()
{
memset(g,0x3f,sizeof(g));
}
int main()
{
init();
int n,m;
cin>>n>>m;
while(m--)
{
int a,b;
cin>>a>>b;
g[a][b]=1;
g[b][a]=1;
}
for(int k=1;k<=n;k++)
{
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(i!=j && g[i][k]+g[k][j]<g[i][j])
g[i][j]=g[i][k]+g[k][j];
}
}
}
int flag=1;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(i==j)
continue;
if(g[i][j]>7)
{
flag=0;
cout<<"No";
return 0;
}
}
}
if(flag) cout<<"Yes";
return 0;
}