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

POJ3680-费用流

2013年12月04日 ⁄ 综合 ⁄ 共 1940字 ⁄ 字号 评论关闭
/*
都说这题是构图很巧的好题~我也赞一个吧,虽然我没有想到。
说说我的思考过程吧。
做这题是因为这题在网络流的分类里面,自然一开始就想构图了~
(1)能作为结点的东西的只有两个,区间和端点,区间没什么道理,以端点做结点的话,离散化是要的;
(2)k限制流量用,段的权值与流量没什么关系,是一种费用性的东西,所以是费用流;
(3)考虑到区间包含连续的点,我画了一个S->1->2->...->T的线图(流量限制为k,费用暂时为0),并尝试对区间(a,b)(权值为w)加边add(S,a,w,1)和add(b,T,w,1),但又捣乱了流量关系,于是继续凌乱中~
在哪个路口乱了咧?没理清楚的流量关系~差一点了!
建图改成代码中的那样后,即add(S,1,0,k),add(cnt,T,0,k),add(i,i+1,0,k),add(a,b,-w,1),a到b的流量一旦形成,a和b之间的点因为在a点之后,流量自然会超限,b之后的点流量也不会受影响,太可爱了!如果这个完整的思考过程属于我就爽了,ok,不写了,老友记ing。
*/
#include <cstdio>
#include <cstring>
#include <stack>
#include <queue>
#include <iostream>
using namespace std;

const int NN=500;
const int MM=10000;
const int INF=0x3fffffff;

struct node{
    int a,b,w;
}p[NN];
int S,T,NV,en,head[NN];
struct Edge{
    int u,v,f,c,next;
}e[MM];
void add(int u,int v,int c,int f)
{
    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 mcmf()
{
    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 hash[100005];
int main()
{
    int cas,n,k,a,b,c;
    scanf("%d",&cas);
    while (cas--)
    {
        memset(hash,0,sizeof(hash));
        scanf("%d%d",&n,&k);
        for (int i=0; i<n; i++)
        {
            scanf("%d%d%d",&p[i].a,&p[i].b,&p[i].w);
            hash[p[i].a]=hash[p[i].b]=1;
        }
        int cnt=0;
        for (int i=1; i<=100000; i++)
            if (hash[i]) hash[i]=++cnt;

        S=0; T=cnt+1; NV=T+1; en=0;
        for (int i=0; i<NV; i++) head[i]=-1;

        for (int i=0; i<=cnt; i++) add(i,i+1,0,k);
        for (int i=0; i<n; i++)  add(hash[p[i].a],hash[p[i].b],-p[i].w,1);

        printf("%d\n",-mcmf());
    }
    return 0;
}

抱歉!评论已关闭.