此题最大最小搞的太复杂。。。并查集维护连通块,连通块内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;
}