已知一个连通的图。从原图中选出一些边,确保图保持连通性。要求在选出的边中,最大边的值要尽量小。
根据XX 定理,要求的值即为该图的最小生成树的最大边。用kruskal或prim均可解决。
不过今天,我们换一下做法。
一,用bellman-ford变形来做,其中用到了bellman-ford的优化版本,基于栈的spfa#include <iostream> using namespace std; int N,M; struct Node { int end,length,next; }edges[22005]; int index; void InsertEdge(int a,int b,int length) { edges[index].end=b; edges[index].length=length; edges[index].next=edges[a].next; edges[a].next=index; ++index; } int stack[2002],ans[2002]; bool inStack[2002]; void SPFA(int a) { memset(inStack,0,sizeof(inStack)); int stackIndex=0; stack[stackIndex++]=a; ans[a]=0; inStack[a]=true; while(stackIndex) { int s=stack[--stackIndex]; inStack[s]=false; int tmp=edges[s].next; while(tmp>0) { if(ans[edges[tmp].end]>max(ans[s],edges[tmp].length)) { ans[edges[tmp].end]=max(ans[s],edges[tmp].length); if(!inStack[edges[tmp].end]) inStack[edges[tmp].end]=true,stack[stackIndex++]=edges[tmp].end; } tmp=edges[tmp].next; } } } int main() { scanf("%d%d",&N,&M); index=N; memset(edges,-1,sizeof(edges)); for(int i=0;i<N;i++) ans[i]=1000000005; int s,t,len; for(int i=0;i<M;i++) { scanf("%d%d%d",&s,&t,&len); --s,--t; InsertEdge(s,t,len); InsertEdge(t,s,len); } SPFA(0); int result=0; for(int i=1;i<N;i++) result=max(result,ans[i]); printf("%d/n",result); return 0; }
二,二分+DFS测试连通性
#include <iostream> #include <algorithm> using namespace std; int N,M; struct Node { int s,t,len; }nodes[20010]; bool operator<(const Node& a,const Node& b) { return a.s<b.s; } int index[2005]; bool visited[2005]; int cnt; void DFS(int s,int limit) { cnt++; for(int i=index[s];i<index[s+1];i++) { if(!visited[nodes[i].t]&&nodes[i].len<=limit) { visited[nodes[i].t]=true; DFS(nodes[i].t,limit); } } } bool Check(int limit) { memset(visited,0,sizeof(visited)); visited[1]=true; cnt=0; DFS(1,limit); if(cnt==N) return true; else return false; } int main() { scanf("%d%d",&N,&M); for(int i=0;i<M;i++) { scanf("%d%d%d",&nodes[i].s,&nodes[i].t,&nodes[i].len); nodes[i+M].s=nodes[i].t; nodes[i+M].t=nodes[i].s; nodes[i+M].len=nodes[i].len; } M*=2; sort(nodes,nodes+M); nodes[M].s=N+1; int p=0; for(int i=1;i<=N;i++) { while(nodes[p].s==i-1) p++; index[i]=p; } index[N+1]=M; int left=0,right=1000000000,ans; while(left<right) { ans=(left+right)/2; if(Check(ans)) right=ans; else left=ans+1; } printf("%d/n",right); return 0; }