此题最大最小搞的太复杂。。。并查集维护连通块,连通块内floyd就可以了
#include <iostream> #include <cstring> #include <string> #include <cstdio> #include <cmath> #include <algorithm> #include <vector> #include <queue> #include <map> #define inf 0x3f3f3f3f #define eps 1e-6 #define ll __int64 using namespace std; vector<int> part[1010]; int mp[1010][1010],n,r[1010],t[1010],vis[1010],dis[1010][1010]; int root(int a) { if(r[a]==a) return a; return r[a]=root(r[a]); } void merge(int a,int b) { int ra=root(a); int rb=root(b); if(ra!=rb) r[ra]=rb; } int floyd(int s) { int m,i,j,k,mmax,mmin; m=part[s].size(); for(i=0;i<m;i++) { for(j=0;j<m;j++) { int a=part[s][i]; int b=part[s][j]; dis[i][j]=mp[a][b]==-1?inf:mp[a][b]; } } for(k=0;k<m;k++) for(i=0;i<m;i++) for(j=0;j<m;j++) dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]); mmin=inf; for(i=0;i<m;i++) { mmax=0; for(j=0;j<m;j++) mmax=max(mmax,dis[i][j]); mmin=min(mmin,mmax+t[part[s][i]]); } return mmin; } int main() { int i,j,ans[1010]; while(~scanf("%d",&n)) { for(i=0;i<=n;i++) { r[i]=i; part[i].clear(); } for(i=0;i<n;i++) for(j=0;j<n;j++) { scanf("%d",&mp[i][j]); if(mp[i][j]!=-1) merge(i,j); } for(i=0;i<n;i++) scanf("%d",&t[i]); for(i=0;i<n;i++) part[root(i)].push_back(i); memset(vis,0,sizeof vis); int aa=0; for(i=0;i<n;i++) { int tmp=root(i); if(!vis[tmp]) { vis[tmp]=1; aa=max(aa,floyd(tmp)); } } printf("%d\n",aa); } return 0; }
zoj3080 ChiBi --- floyd求连通块内最短路,布布扣,bubuko.com
zoj3080 ChiBi --- floyd求连通块内最短路
原文:http://blog.csdn.net/u011032846/article/details/35284417