贪心,之前先bfs判断是否联通,然后,反向建图,找一个未选择的点,找与他距离最近的点连边,因为每个点都要被选择,所以一个点离他最近的另一个点肯定也被选择,可以贪心
#include<queue> #include<cstdio> #include<vector> #include<Cstring> #include<iostream> using namespace std; const int inf=1<<29; vector<int>graph[1010]; vector<int>num; int n,m,ans,cnt,pos; int q[1010],out[1010],head[10010],next[10010],to[10010],used[10010],w[10010]; void insert(int u,int v,int c) { next[++cnt]=head[u]; head[u]=cnt; to[cnt]=v; w[cnt]=c; } bool bfs(int x) { int tot=1; queue<int>q; q.push(x); used[x]=1; while(!q.empty()) { int u=q.front(); q.pop(); for(int i=0;i<graph[u].size();i++) { int v=graph[u][i]; if(!used[v]) { tot++; q.push(v); used[v]=1; } } } return tot==n; } void go(int x) { int u=x; used[pos]=1; while(u!=pos) { int MIN=inf,x; used[u]=1; for(int i=head[u];i;i=next[i]) { int v=to[i],cost=w[i]; if(cost<MIN) { MIN=cost; x=v; } } ans+=MIN; if(used[x]) break; u=x; } } int main() { scanf("%d",&n); int MAX=0; for(int i=1;i<=n;i++) { scanf("%d",q+i); if(MAX<q[i]) { MAX=q[i]; pos=i; } } scanf("%d",&m); for(int i=1;i<=m;i++) { int u,v,c; scanf("%d%d%d",&u,&v,&c); graph[u].push_back(v); insert(v,u,c); // out[u]++; } if(!bfs(pos)) { cout<<-1; return 0; } memset(used,0,sizeof(used)); /* for(int i=1;i<=n;i++) { if(out[i]==0) num.push_back(i); }*/ for(int i=1;i<=n;i++) { if(!used[i]) go(i); } cout<<ans; return 0; }