一.Prim 算法
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;
}
二.Kruskal算法
复杂度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;
}
三.POJ 3255 Roadblocks
题意:给你一幅图然你求第二短路
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]);
}
四.POJ 3723 Conscription
题意: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());
}
五.POJ 3169
题意: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);
}