zoukankan      html  css  js  c++  java
  • UVA 10806 Dijkstra, Dijkstra.

    UVA_10806

        这个题目我们可以把边的容量设为1,费用设为权值,然后再引入一条边N-N+1,容量设为2,费用设为0,然后去求1N+1的最小费用最大流,如果到N+1的流量为2,则输出最小费用,否则就是无解。

    在老大的指点下,自己亲手把以前没有写过的费用流的邻接表形式写了一遍。

    费用流应用邻接表时需要注意三个问题:

    ①要把一条边的正向边和反向边各建一次,如果是无向图,可以把一个无向边看成两个有向边,然后建四条边存储。

    ②在建边时多开一个数组op[],用于存储此边的反向边的标号,便于增广。

    ③在记录父节点时,同时多开一个数组edge[],用于记录父节点连向该节点的有向边的标号,用于增广。

    有了邻接表形式的费用流,就可以求解存在平行边和反向边的费用流问题了。

    #include<stdio.h>
    #include<string.h>
    int first[110],next[40010],v[40010],op[40010];
    int flow[40010],cost[40010],cap[40010];
    int q[110],inq[110],p[110],edge[110],d[110],N,M,E;
    int init()
    {
    int i,a,b,w,e;
    scanf("%d",&N);
    if(!N)
    return 0;
    scanf("%d",&M);
    e=0;
    memset(first,-1,sizeof(first));
    for(i=0;i<M;i++)
    {
    scanf("%d%d%d",&a,&b,&w);
    v[e]=b;
    cap[e]=1;
    cost[e]=w;
    next[e]=first[a];
    first[a]=e;
    op[e]=e+1;
    e++;
    v[e]=a;
    cap[e]=0;
    cost[e]=-w;
    next[e]=first[b];
    first[b]=e;
    op[e]=e-1;
    e++;
    v[e]=a;
    cap[e]=1;
    cost[e]=w;
    next[e]=first[b];
    first[b]=e;
    op[e]=e+1;
    e++;
    v[e]=b;
    cap[e]=0;
    cost[e]=-w;
    next[e]=first[a];
    first[a]=e;
    op[e]=e-1;
    e++;
    }
    v[e]=N+1;
    cap[e]=2;
    cost[e]=0;
    next[e]=first[N];
    first[N]=e;
    op[e]=e+1;
    e++;
    v[e]=N;
    cap[e]=0;
    cost[e]=0;
    next[e]=first[N+1];
    first[N+1]=e;
    op[e]=e-1;
    e++;
    E=e;
    return 1;
    }
    int check()
    {
    int i,j,k,e,a,f,c,u,rear,front;
    memset(flow,0,sizeof(flow));
    f=c=0;
    while(1)
    {
    front=rear=0;
    memset(inq,0,sizeof(inq));
    for(i=1;i<=N+1;i++)
    d[i]=1000000001;
    d[1]=0;
    q[rear++]=1;
    inq[1]=1;
    while(front!=rear)
    {
    u=q[front++];
    inq[u]=0;
    if(front>N+1)
    front=0;
    for(e=first[u];e!=-1;e=next[e])
    if(d[u]+cost[e]<d[v[e]]&&cap[e]>flow[e])
    {
    d[v[e]]=d[u]+cost[e];
    p[v[e]]=u;
    edge[v[e]]=e;
    if(!inq[v[e]])
    {
    q[rear++]=v[e];
    if(rear>N+1)
    rear=0;
    inq[v[e]]=1;
    }
    }
    }
    if(d[N+1]>1000000000)
    break;
    a=1000000001;
    for(u=N+1;u!=1;u=p[u])
    {
    e=edge[u];
    if(cap[e]-flow[e]<a)
    a=cap[e]-flow[e];
    }
    for(u=N+1;u!=1;u=p[u])
    {
    e=edge[u];
    flow[e]+=a;
    flow[op[e]]-=a;
    }
    c+=d[N+1]*a;
    f+=a;
    }
    if(f==2)
    return c;
    else
    return -1;
    }
    int main()
    {
    int k;
    while(init())
    {
    k=check();
    if(k<0)
    printf("Back to jail\n");
    else
    printf("%d\n",k);
    }
    return 0;
    }


  • 相关阅读:
    require的特点
    require和load的不同之处
    关于“load”方法
    puts方法要点
    用类解释对象的由来
    以方法调用的原理解释Ruby中“puts ‘Hello‘”
    Ruby中方法的设计理念
    Ruby中puts,print,p的区别
    Ubuntu16.04安装MongoDB的Ruby驱动
    使用spring框架,用xml方式进行bean装配出现“The fully qualified name of the bean's class, except if it serves...”
  • 原文地址:https://www.cnblogs.com/staginner/p/2196903.html
Copyright © 2011-2022 走看看