码迷,mamicode.com
首页 > 其他好文 > 详细

LibreOJ 6001 太空飞行计划(最大流)

时间:2018-03-14 22:05:44      阅读:140      评论:0      收藏:0      [点我收藏+]

标签:std   pre   empty   char   body   class   amp   void   无限   

技术分享图片

技术分享图片

题解:首先源点向每个实验建边,流量为经费的值,实验向器材建边,值为无限大,器材向终点建边,值为价值

然后跑一遍最大流就能跑出所谓的最大闭合图的点值之和.

代码如下:

#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define hi puts("hi");
#define inf 0x3f3f3f3f
using namespace std;

int v[100010],w[100010],head[100010],next[100010],deep[100010],first[100010],cur[100010];
int n,m,s,t,cnt;

void init()
{
    cnt=-1;    //
    memset(head,-1,sizeof(head));
    memset(next,-1,sizeof(next));
}

void add(int from,int to,int cost)
{
    cnt++;
    next[cnt]=head[from];   //
    v[cnt]=to;
    w[cnt]=cost;
    head[from]=cnt;
}

void add_edge(int from,int to,int cost)
{
    add(from,to,cost);
    add(to,from,0);
}

int bfs(int s,int t)
{
    queue<int> q;
    memset(deep,0,sizeof(deep));
    deep[s]=1;
    q.push(s);
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        for(int i=head[u]; i!=-1; i=next[i])
        {
            if(w[i]>0&&(!deep[v[i]]))
            {
                deep[v[i]]=deep[u]+1;
                q.push(v[i]);
            }
        }
    }
    if(!deep[t])
    {
        return 0;
    }
    return 1;
}

int dfs(int u,int t,int dist)
{
    if(u==t)
    {
        return dist;
    }
    for(int i=head[u]; i!=-1; i=next[i])
    {
        if(w[i]&&(deep[v[i]]==deep[u]+1))  //!!!
        {
            int di=dfs(v[i],t,min(dist,w[i]));
            if(di>0)
            {
                w[i]-=di;
                w[i^1]+=di;
                return di;
            }
        }
    }
    return 0;
}

int dinic(int s,int t)
{
    int ans=0;
    while(bfs(s,t))
    {
        while(int d=dfs(s,t,inf))
        {
            ans+=d;
        }
    }
    return ans;
}


int main()
{
    init();
    scanf("%d%d",&m,&n);
    int sum=0;
    s=0;
    t=n+m+1;
    int x;
    char c;
    for(int i=1; i<=m; i++)
    {
        scanf("%d",&x);
        sum+=x;
        add_edge(s,n+i,x);
        while(1)
        {
            scanf("%d%c",&x,&c);
            add_edge(n+i,x,inf);
            if(c==\n||c==\r)
            {
                break;
            }
        }
    }
    for(int i=1; i<=n; i++)
    {
        scanf("%d",&x);
        add_edge(i,t,x);
    }
    sum-=dinic(s,t);
    for(int i=1;i<=m;i++)
    {
        if(deep[i+n])
        {
            printf("%d ",i);
        }
    }
    printf("\n");
    for(int i=1;i<=n;i++)
    {
        if(deep[i])
        {
            printf("%d ",i);
        }
    }
    printf("\n");
    printf("%d\n",sum);
}

 

LibreOJ 6001 太空飞行计划(最大流)

标签:std   pre   empty   char   body   class   amp   void   无限   

原文地址:https://www.cnblogs.com/stxy-ferryman/p/8570090.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!