这道题的题意为:给你一个nxn的矩阵 分别代表 i到j 的距离,再给q条无向边,求使任意两个点能互相到达的最小距离
我的做法 :强连通缩点+最小生成树
//其实这题只用最小生成树可以做的 为了练习强连通而。。
1A 15MS
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <set> #include <vector> #include <map> #include <queue> #include <set> #include <algorithm> using namespace std; #define MAXN 110 #define DIS_INF 10000 int n,q; vector <int> e[MAXN]; int disx[MAXN][MAXN]; int dfn[MAXN],low[MAXN],stack[MAXN],bleg[MAXN]; int top,times; void tarjan(int u){ dfn[u]=low[u]=++times; stack[++top]=u; for(int i=0;i<(int)e[u].size();i++){ int v=e[u][i]; if(!dfn[v]){ tarjan(v); low[u]=min(low[u],low[v]); } else if(!bleg[v]) low[u]=min(low[u],low[v]); } if(dfn[u]==low[u]){ bleg[0]++; do{ bleg[stack[top]]=bleg[0]; }while(stack[top--]!=u); } } void init(){ memset(dfn,0,sizeof(dfn)); memset(bleg,0,sizeof(bleg)); top=times=0; } int tran[MAXN][MAXN]; int disy[MAXN][MAXN]; struct Edge{ int u,v,val; }edge[MAXN*MAXN]; int cmp(Edge x,Edge y){ return x.val<y.val; } int path[MAXN]; int find(int x){ return x==path[x]?x:path[x]=find(path[x]); } int Union(int x,int y){ x=find(x); y=find(y); if(x==y)return false; path[x]=y; return true; } int main() { while(~scanf("%d",&n)){ init(); for(int i=0;i<MAXN;i++)e[i].clear(); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) scanf("%d",&disx[i][j]); scanf("%d",&q); int u,v; while(q--){ scanf("%d%d",&u,&v); e[u].push_back(v); e[v].push_back(u); } for(int i=1;i<=n;i++) if(!dfn[i])tarjan(i); memset(tran,0,sizeof(tran)); for(int i=1;i<=n;i++){ int &num=tran[bleg[i]][0]; tran[bleg[i]][++num]=i; } for(int i=1;i<=bleg[0];i++) for(int j=1;j<=bleg[0];j++) disy[i][j]=DIS_INF; for(int i=0;i<MAXN;i++)path[i]=i; int tot=0; for(int i=1;i<=bleg[0];i++){ int n1=tran[i][0]; int u=i; for(int j=i+1;j<=bleg[0];j++){ int n2=tran[j][0]; int v=j; for(int ii=1;ii<=tran[u][0];ii++){ int uu=tran[u][ii]; for(int jj=1;jj<=tran[v][0];jj++){ int vv=tran[v][jj]; disy[u][v]=disy[v][u]=min(disy[u][v],disx[uu][vv]); } } edge[tot].u=u; edge[tot].v=v; edge[tot].val=disy[u][v]; ++tot; } } sort(edge,edge+tot,cmp); int ans=0; for(int i=0;i<tot;i++){ int u=edge[i].u; int v=edge[i].v; int val=edge[i].val; if(Union(u,v)){ ans+=val; } } printf("%d\n",ans); } return 0; }
|