现在的位置: 首页 > 综合 > 正文

图论 最小生成树 Prim Kruskal POJ 3255 POJ 3723 POJ 3169

2013年12月09日 ⁄ 综合 ⁄ 共 2191字 ⁄ 字号 评论关闭

一.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);
}

【上篇】
【下篇】

抱歉!评论已关闭.