int cost[MXV][MXV]; int mincost[MXV]; bool used[MXV]; int V; int prim(){ for(int i=0;i<V;++i){ mincost[i]=INF; used[i]=false; } mincost[0]=0; int res=0; while(true){ int v=-1; for(int u=0;u<V;++u){ if(!used[u]&&(v==-1||mincost[u]<mincost[v])) v=u; } if(v==-1) break; used[v]=true; res+=mincost[v]; for(int u=0;u<V;++u){ mincost[u]=min(mincost[u],cost[v][u]); } } return res; }
复杂度O(ElogV)
struct edge{int u,v,cost;}; bool cmp(const edge & e1,const edge &e2 ){ return e1.cost<e2.cost; } edge es[MXE]; int V,E; int kruskal(){ sort(es,es+E,cmp); init_union_find(V); int res=0; for(int i=0;i<E;++i){ edge e=es[i]; if(!same(e.u,e.v)){ unite(e.u,e.v); res+=e.cost; } } return res; }
题意:给你一幅图然你求第二短路
int N,R; vector<edge> G[MXN]; int dist[MXN]; int dist2[MXN]; void Fun(){ priority_queue<P,vector<P>,greater<P> > que; fill(dist,dist+N,INF); fill(dist,dist2+N,INF); dist[0]=0; que.push(P(0,0)); while(!que.empty()){ P p=que.top();que.pop(); int v=p.second,d=p.first; if(dist2[v]<d) continue; for(int i=0;i<G[v].size();++i){ edge &e=G[v][i]; int d2=d+e.cost; if(dist[e.to]>d2){ swap(dist[e.to],d2); que.push(P(dist[e.to],e.to)); } if(dist2[e.to]>d2&&dist[e.to]<d2){ dist2[e.to]=d2; que.push(P(dist2(e.to),e.to)); } } } printf("%d\n",dist2[N-1]); }
题意:Windy要组建一支军队,需要招募N个女生和M个男生组成,需要付每个人10000RMB。现在已知这些人中有R组关系,即第x个女生和第y个男生关系为d,如果先招募了其中一个,利用他们的关系去招募另外一个,可以便宜的RMB,问Windy至少要用多少RMB才能组建成这支军队。
解法:
把人看作顶点,关系看作边,求解无向图中的最大权森林.
int N,M,R; int x[MXR],y[MXR],d[MXR]; void Fun(){ V=N+M; E=R; for(int i=0;i<R;++i) es[i]=(edge){x[i],N+y[i],-d[i]}; printf("%d\n",10000*(N+M)+kruskal()); }
题意:n头牛编号为1到n,按照编号的顺序排成一列,每两头牛的之间的距离 >=0。这些牛的距离存在着一些约束关系:1.有ml组(u, v, w)的约束关系,表示牛[u]和牛[v]之间的距离必须<= w。2.有md组(u, v, w)的约束关系,表示牛[u]和牛[v]之间的距离必须>=w。问如果这n头无法排成队伍,则输出-1,如果牛[1]和牛[n]的距离可以无限远,则输出-2,否则则输出牛[1]和牛[n]之间的最大距离
int N,ML,MD; int AL[MXML],BL[MXML],DL[MXML]; int AD[MXMD],BD[MXMD],DD[MXMD]; int d[MXN]; void Fun{ fill(d,d+N,INF); d[0]=0; //用Bellman-Ford算法计算d for(int k=0;k<N;++k){ //从i+1到i的权值为0 for(int i=0;i+1<N;++i) if(d[i+1]<INF) d[i]=min(d[i],d[i+1]); //从AL到BL的权值为DL for(int i=0;i<ML;++i) if(d[AL[i]-1]<INF) d[BL[i]-1]=min(d[BL[i]-1],d[AL[i]-1]+DL[i]); //从BD到AD的权值为-DD for(int i=0;i<MD;++i) if(d[BD[i]-1]<INF) d[AD[i]-1]=min(d[AD[i]-1],d[BD[i]-1]-DD[i]); } int res=d[N-1]; if(d[0]<0) res=-1; else if(res==INF) res=-2; printf("%d\n",res); }