HDU 4411 Arrest【最小费用最大流】

题意: 有 n+1 个城市编号 0..n,有 m 条无向边,在 0 城市有个警察总部,最多可以派出 k 个逮捕队伍,在1..n 每个城市有一个犯罪团伙,
          每个逮捕队伍在每个城市可以选择抓或不抓,如果抓了 第 i  个城市的犯罪团伙,第 i-1 个城市的犯罪团伙就知道了消息  ,如果第 i-1 的犯罪

          团伙之前没有被抓,任务就失败,问要抓到所有的犯罪团伙,派出的队伍需要走的最短路是多少。

分析: 最小费用最大流,需要注意的地方在于怎么去保证每个每个城市的团伙仅仅被抓一次,且在抓他之前,第i-1城市的团伙已经被抓。

          方法是把拆点后的城市 i 和 i`之间的费用要设成一个很小的负值,这样可以保证该城市一定可以被访问到,

          还有一点要注意的是派出的k个队可能有些队是不执行任务的,

          方法是在 0 节点和 汇点之间连一条费用为0,容量为k的边

          具体建图:

          源点 s=2*n+1,

          汇点 t=2*n+2,

          每个城市拆成两个点 i 和 i+n,费用为 -100000,容量为 1

          在源点和 0 之间连一条费用为 0 容量为 k 的边

          在 0 和 城市 1..n之间连一条费用为 0 到 i 最短路容量为 1 的边(表示出发)

          在 城市 n+1..n+n到汇点之间连一条费用为 0 到 i 最短路容量为 1 的边(表示回到总部)

          在 城市 n+i..n+n 和 j(j>i)直间连一条费用为城市 i 到 j 最短路距离容量为 1 的边

          求最小费用流。

#include<stdio.h>
#include<string.h>
#define clr(x)memset(x,0,sizeof(x))
#define INF 0x1f1f1f1f
#define min(a,b)(a)<(b)?(a):(b)
#define max(a,b)(a)>(b)?(a):(b)
struct node
{
    int next,from,to,w,c;
}e[1000010];
int tot;
int head[210];
void add(int st,int u,int wi,int flow)
{
    e[tot].from=st;
    e[tot].to=u;
    e[tot].w=wi;
    e[tot].c=flow;
    e[tot].next=head[st];
    head[st]=tot++;

    e[tot].from=u;
    e[tot].to=st;
    e[tot].w=-wi;
    e[tot].c=0;
    e[tot].next=head[u];
    head[u]=tot++;
}
int q[100010];
int pre[2010];
int dis[2010];
int v[220];
int s,t;
int spfa()
{
    int i,x,front,rear,k;
    front=rear=0;
    for(i=0;i<=t;i++)
        dis[i]=INF;
    clr(v);
    pre[s]=-1;
    q[rear++]=s;
    dis[s]=0;
    v[s]=1;
    while(front<rear)
    {
        x=q[front++];
        v[x]=0;
        for(i=head[x];i!=-1;i=e[i].next)
        {
            k=e[i].to;
            if(e[i].c&&dis[x]+e[i].w<dis[k])
            {
                dis[k]=dis[x]+e[i].w;
                pre[k]=i;
                if(!v[k])
                {
                    v[k]=1;
                    if(dis[k]<=dis[x]&&front>0)
                        q[--front]=k;
                    else q[rear++]=k;
                }
            }
        }
    }
    if(dis[t]!=INF)
        return 1;
    return 0;
}
int costflow()
{
    int tt=0;
    int tot=0,flow=0,u,minf=INF;
    while(spfa())
    {
        for(u=pre[t];u!=-1;u=pre[e[u].from])
            minf=min(minf,e[u].c);
        for(u=pre[t];u!=-1;u=pre[e[u].from])
        {
            e[u].c-=minf;
            e[u^1].c+=minf;
            flow+=e[u].w*minf;
        }
    }
    return flow;
}
int g[105][105];
int main()
{
    int m,n,a,b,c,k,K,w,z,i,j;
    while(scanf("%d%d%d",&n,&m,&K)!=EOF)
    {
        if(n==0&&m==0&&K==0)
            break;
        memset(g,INF,sizeof(g));
        for(i=0;i<=n;i++)
            g[i][i]=0;
        while(m--)
        {
            scanf("%d%d%d",&a,&b,&w);
            if(w<g[a][b])
                g[a][b]=g[b][a]=w;
        }
        for(k=0;k<=n;k++)
            for(i=0;i<=n;i++)
                for(j=0;j<=n;j++)
                    if(g[i][k]+g[k][j]<g[i][j])
                        g[i][j]=g[i][k]+g[k][j];
        int res;
        s=2*n+1;
        t=2*n+2;
        tot=0;
        memset(head,-1,sizeof(head));
        add(s,0,0,K);
        add(0,t,0,w);
        for(i=1;i<=n;i++)
        {
            add(0,i,g[0][i],1);
            add(i,i+n,-1000000,1);
            add(i+n,t,g[0][i],1);
        }
        for(i=1;i<=n;i++)
            for(j=i+1;j<=n;j++)
                add(i+n,j,g[i][j],1);
        printf("%d\n",costflow()+1000000*n);
    }
    return 0;
}

 

posted @ 2012-09-24 19:59  'wind  阅读(676)  评论(0编辑  收藏  举报