HDOJ4411-费用流

有个明显的关系:处理i城市之前必须处理掉i-1城市~~

先floyed求出各点间的距离mp[i][j],

把n个点一分为3(P1i,P2i,P3i),源点S,汇点T,建图如下:

1)S向P11连一条流量为k,费用为零的边:(k个小队)

2)P1i向P1(i+1)连一条流量为k,费用为零的边:(没去i城市的小队可去i+1城市)

2)P1i向P2i连一条流量为1,费用为mp[0][i]的边:(一个小队从0城市出发到了i城市)

3)P2i向T连一条流量为1,费用为mp[i][0]的边:(回到0城市)

4)S向P3i连一条流量为1,费用为零的边:(处理了i城市后的小队还可以去别的城市做任务)

5)P3i向P2j(i<j)连一条流量为1,费用为mp[i][j]-mp[i][0]的边:(去i城市的小队没有直接回去而是又去了j城市)

以上建图方案能满足“处理i城市之前必须处理掉i-1城市”的关系,因为每个小队都是按顺序去的各地~~

代码如下:

#include <cstdio>
#include <stack>
#include <cstring>
#include <iostream>
using namespace std;

const int NN=500;
const int MM=300000;
const int INF=0x3f3f3f3f;

int n,mp[NN][NN];
void floyed()
{
    for (int k=0; k<=n; k++)
        for (int i=0; i<=n; i++) if (k!=i)
             for (int j=0; j<=n; j++) if (k!=j && i!=j)
                  if (mp[i][k]+mp[k][j]<mp[i][j]) mp[i][j]=mp[i][k]+mp[k][j];
}

int S,s,T,NV,en,head[NN];
struct Edge
{
    int u,v,f,c,next;
} e[MM];
void add(int u,int v,int f,int c)
{
    e[en].u=u; e[en].v=v; e[en].c=c; e[en].f=f; e[en].next=head[u];
    head[u]=en++;
    e[en].u=v; e[en].v=u; e[en].c=-c; e[en].f=0; e[en].next=head[v];
    head[v]=en++;
}

int dis[NN],fa[NN];
bool vis[NN];
bool spfa()
{
    for (int i=0; i<NV; i++) dis[i]=INF;
    dis[S]=0;
    fa[S]=-1;
    stack<int> q;
    q.push(S);
    while (!q.empty())
    {
        int u=q.top();
        q.pop();
        vis[u]=false;
        for (int i=head[u]; i!=-1; i=e[i].next)
        {
            int v=e[i].v;
            if (e[i].f && dis[v]>dis[u]+e[i].c)
            {
                dis[v]=dis[u]+e[i].c;
                fa[v]=i;
                if (!vis[v])
                {
                    vis[v]=true;
                    q.push(v);
                }
            }
        }
    }
    if (dis[T]!=INF) return true;
    else             return false;
}

int fee_flow()
{
    int max_flow=0;
    int min_cost=0;
    while (spfa())
    {
        int flow=INF;
        int u,v;
        for (v=T; fa[v]!=-1; v=u)
        {
            u=e[fa[v]].u;
            if (flow>e[fa[v]].f) flow=e[fa[v]].f;
        }
        for (v=T; fa[v]!=-1; v=u)
        {
            u=e[fa[v]].u;
            e[fa[v]].f-=flow;
            e[fa[v]^1].f+=flow;
        }
        max_flow+=flow;
        min_cost+=dis[T];
    }
    return min_cost;
}

int p1[NN],p2[NN],p3[NN];
int main()
{
    int m,k,u,v,w;
    while (scanf("%d%d%d",&n,&m,&k),n|m|k)
    {
        memset(mp,0x3f,sizeof(mp));
        for (int i=1; i<=m; i++)
        {
            scanf("%d%d%d",&u,&v,&w);
            if (mp[u][v]>w) mp[u][v]=mp[v][u]=w;
        }

        floyed();

        memset(head,-1,sizeof(head));
        en=S=0; T=3*n+1; NV=T+1;
        for (int i=1; i<=n; i++)
        {
            p1[i]=i;
            p2[i]=i+n;
            p3[i]=i+2*n;
        }
        add(S,1,k,0);
        for (int i=1; i<n; i++) add(p1[i],p1[i+1],k,0);
        for (int i=1; i<=n; i++) add(p1[i],p2[i],1,mp[0][i]);
        for (int i=1; i<n; i++) add(S,p3[i],1,0);
        for (int i=1; i<=n; i++) add(p2[i],T,1,mp[0][i]);
        for (int i=1; i<n; i++)
          for (int j=i+1; j<=n; j++) add(p3[i],p2[j],1,mp[i][j]-mp[0][i]);
        printf("%d\n",fee_flow());
    }
    return 0;
}

你可能感兴趣的:(c,struct,任务)