http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=4004
题意:给你一副图,求使得给定三个点连通的最小代价,大概就这样,具体看题目吧
斯坦那树有一个结论:n个点的斯坦那树至少会经过n-2个中间节点,这里n=3,所以至少会经过一个中间节点,求出这三个点的单源最短路后枚举中间节点即可。
把m写成n,WA了数遍,实在是太水了
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#include<algorithm>
using namespace std;
const int inf = 0x7fffffff / 3;
const int maxn = 510;
int dis1[maxn],dis2[maxn],dis3[maxn];
vector<pair<int,int> > edge[maxn];
bool vis[maxn];
int n,m;
void spfa(int s,int dis[],int n)
{
memset(vis,false,sizeof(vis));
fill(dis,dis+n+1,-1);
dis[s]=0;
queue<int> Q;Q.push(s);
while(!Q.empty()){
int fr=Q.front();Q.pop();
vis[fr]=false;
for(int i=0;i<edge[fr].size();i++)
{
int v=edge[fr][i].first,w=edge[fr][i].second;
if(dis[v]==-1 || dis[v]>dis[fr]+w)
{
dis[v]=dis[fr]+w;
if(!vis[v])
{
vis[v]=true;
Q.push(v);
}
}
}
}
}
void Min(int &a,int b){
if(a==-1 || b<a) a=b;
}
int t[10010];
int main()
{
int L,q,ca=1;
while(scanf("%d%d%d",&n,&m,&L)!=EOF)
{
for(int i=1;i<=m;i++) edge[i].clear();
for(int i=1;i<=n;i++) scanf("%d",&t[i]);
int a,b,c;
for(int i=1;i<=L;i++)
{
scanf("%d%d%d",&a,&b,&c);
edge[a].push_back(make_pair(b,c));
edge[b].push_back(make_pair(a,c));
}
printf("Case #%d\n",ca++);
scanf("%d",&q);
for(int k=1;k<=q;k++)
{
scanf("%d%d%d",&a,&b,&c);
a=t[a];b=t[b];c=t[c];
spfa(a,dis1,m);
spfa(b,dis2,m);
spfa(c,dis3,m);
int ans=-1;
for(int i=1;i<=m;i++)
{
if(dis1[i]==-1 || dis2[i]==-1 || dis3[i]==-1) continue;
Min(ans,dis1[i]+dis2[i]+dis3[i]);
}
printf("Line %d: ",k);
if(ans==-1) puts("Impossible to connect!");
else printf("The minimum cost for this line is %d.\n",ans);
}
}
return 0;
}