题目链接:http://soj.sysu.edu.cn/13984
题意:
n个农场,每个农场间可能存在想通的路,给出M对具有边权的边(可能有重边),对于Q个查询,输出想通的路的个数和总的最小距离。
要求路径中必须至少含有包括农场1、2、3....K之中的一个。
分析:简单的floyd再加上一些判断。
先用floyd算法求出每个点与其它点的最短距离。
然后通过添加1、2.....K作为路径其中的点,然后求出最终的最小值。
代码实现:
//题目:SOJ 13984
//时间:2015-4-12 00:26
//作者:Miki
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<map>
#include<string>
#include<queue>
#include<utility>
using namespace std;
typedef long long LL;
const LL INF=1e15;
const int MAX=210;
int n,m,K,q;;
LL edge[MAX][MAX];
void floyd()
{
for(int k=1;k<=n;k++)
{
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(edge[i][k]+edge[k][j]<edge[i][j])
{
edge[i][j]=edge[i][k]+edge[k][j];
}
}
}
}
}
int main()
{
// freopen("in.txt","r",stdin);
int u,v;
LL w;
while(scanf("%d %d %d %d",&n,&m,&K,&q)!=EOF)
{
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(i==j)
edge[i][j]=0;
else
edge[i][j]=INF;
}
}
for(int i=0;i<m;i++)
{
scanf("%d %d %lld",&u,&v,&w);
edge[u][v]=min(edge[u][v],w);//判重边
}
floyd();
LL cnt=0,sum=0;
for(int i=0;i<q;i++)
{
scanf("%d %d",&u,&v);
//添加路径中的点
LL temp=INF;
for(int k=1;k<=K;k++)
if(edge[u][k]+edge[k][v]<temp)
temp=edge[u][k]+edge[k][v];
if(temp!=INF)
{
cnt++;
sum+=temp;
}
}
printf("%lld\n%lld\n",cnt,sum);
}
return 0;
}