题目:https://vjudge.z180.cn/problem/Kattis-dragonball1
题意:n个点,m条边,每条边有个权值,然后给7个点,求从1开始走,直到把7个点全部走完的最短路
题解:求1到所有点的最短路,然后分别求以这个7个点为起点的最短路,总共8个最短路,,因为总共7个点,所以枚举这7个点的所有排列方式就可以了。
这里用到了一个全排列函数:next_permutation
还用到了memset赋最大值,memset中赋值用0x3f,和inf,最后结果一样
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll inf=0x3f3f3f3f3f3f3f3f;
const int N=1e6+9;
int head[N],ver[N],edge[N],nex[N];
ll d[10][N];
int n,m,tol,idx;
bool vis[N];
void add(int x,int y,int z)
{
ver[++idx]=y,nex[idx]=head[x],edge[idx]=z,head[x]=idx;
}
void spfa(int pos) //spfa模板
{
queue<int>q;
memset(vis,0,sizeof(vis));
q.push(pos);
vis[pos]=1;
d[tol][pos]=0; //tol是第几个最短路
while(!q.empty())
{
int x=q.front();
q.pop();
vis[x]=0;
for(int i=head[x]; i>=0; i=nex[i])
{
int y=ver[i],z=edge[i];
if(d[tol][y]>d[tol][x]+z)
{
d[tol][y]=d[tol][x]+z;
if(!vis[y])q.push(y),vis[y]=1;
}
}
}
tol++; //tol++
}
int main()
{
memset(head,-1,sizeof head);
memset(d,0x3f,sizeof d);
scanf("%d%d",&n,&m);
for(int i=0; i<m; i++) //建边
{
int a,b,t;
scanf("%d%d%d",&a,&b,&t);
add(a,b,t),add(b,a,t);
}
spfa(1); //求1为起点的最短路
int temp[10];
int pai[]= {1,2,3,4,5,6,7}; //代表第几个最短路,然后枚举这几个最短路的排列方式
for(int i=1; i<=7; i++)
{
scanf("%d",&temp[i]);
spfa(temp[i]); //求以它为起点的最短路
}
ll minn=inf;
do //枚举这7个点的排列方式,即走法
{
ll s=d[0][temp[pai[0]]]; //第0个最短路(即以1为起点)
s+=d[pai[0]][temp[pai[1]]]; //d的第一维存的是第几个最短路,就是pai的值
s+=d[pai[1]][temp[pai[2]]]; //然后以这个为起点找它的下一条边
s+=d[pai[2]][temp[pai[3]]];
s+=d[pai[3]][temp[pai[4]]];
s+=d[pai[4]][temp[pai[5]]];
s+=d[pai[5]][temp[pai[6]]];
minn=min(s,minn); //求最小
}
while(next_permutation(pai,pai+7));//全排列函数
if(minn<inf)printf("%lld\n",minn);
else printf("-1\n");
return 0;
}