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; }