HDU 3395 Special Fish 最“大”费用最大流

求最大费用可以将边权取负以转化成求最小费用。然而此时依然不对,因为会优先寻找最大流,但是答案并不一定出现在满流的时候。所以要加一些边(下图中的红边)使其在答案出现时满流。设所有边的流量为1,花费如下图所示。显然最大花费是1001,而没有红边的情况下会得到3。

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <queue>
#include <cmath>
#include <stack>
#include <map>

#pragma comment(linker, "/STACK:1024000000");
#define EPS (1e-8)
#define LL long long
#define ULL unsigned long long
#define _LL __int64
#define INF 0x3f3f3f3f
#define Mod 6000007

using namespace std;

struct E
{
    int u,v,Max,cost,next;
}edge[200100];

int head[310];
int cur[310];

int Top;

void Link(int u,int v,int w,int cost)
{
    edge[Top].u = u;
    edge[Top].v = v;
    edge[Top].cost = cost;
    edge[Top].Max = w;
    edge[Top].next = head[u];
    head[u] = Top++;
}

struct Q
{
    int v;
//    bool operator < (const Q &a) const {
//        return a.cost < cost;
   // }
};

void Updata(int site,int flow,int &cost)
{
    for(int i = site;cur[i] != -1; i = edge[cur[i]^1].v)
    {
        edge[cur[i]].Max -= flow;
        edge[cur[i]^1].Max += flow;
        cost += edge[cur[i]].cost*flow;
    }
}

int dis[310];
int flow[310];

bool mark[310];

queue<Q> q;

int Spfa(int S,int T,int n,int &cost)
{
    while(q.empty() == false)
        q.pop();

    memset(mark,false,sizeof(bool)*(n+2));
    memset(dis,INF,sizeof(int)*(n+2));
    memset(flow,INF,sizeof(int)*(n+2));
    dis[S] = 0;

    Q f,t;

    f.v = S;
    dis[S] = 0;
    cur[S] = -1;
    mark[S] = true;
    q.push(f);

    while(q.empty() == false)
    {
        f = q.front();
        q.pop();
        mark[f.v] = false;
        for(int p = head[f.v]; p != -1; p = edge[p].next)
        {
            t.v = edge[p].v;

            if(edge[p].Max && dis[t.v] > dis[f.v] + edge[p].cost)
            {
                cur[t.v] = p;
                dis[t.v] = dis[f.v] + edge[p].cost;
                flow[t.v] = min(flow[f.v],edge[p].Max);

                if(mark[t.v] == false)
                {
                    mark[t.v] = true;
                    q.push(t);
                }
            }
        }
    }

    if(dis[T] != INF)
    {
        Updata(T,flow[T],cost);
        return flow[T];
    }

    return 0;
}

int Cal_MaxFlow_MinCost(int S,int T,int n)
{
    int f = 0,cost = 0,temp;

    do
    {
        temp = Spfa(S,T,n,cost);
        f += temp;
    }while(temp);

    printf("%d\n",-cost);

    return cost;
}

int val[110];

int main()
{
    int n;

    int u,v,w,i,j,x;

    while(scanf("%d",&n) && n)
    {
        memset(head,-1,sizeof(int)*(2*n+3));
        Top = 0;
        for(i = 1;i <= n; ++i)
        {
            scanf("%d",&val[i]);
        }

        int S = 1,T = 2*n+2;

        for(i = 1;i <= n; ++i)
        {
            Link(S,i+1,1,0);
            Link(i+1,S,0,0);
            Link(n+i+1,T,1,0);
            Link(T,n+i+1,0,0);
            Link(i+1,T,1,0);
            Link(T,i+1,0,0);
        }

        for(i = 1;i <= n; ++i)
        {
            for(j = 1;j <= n; ++j)
            {
                scanf("%1d",&x);
                if(x)
                {
                    Link(i+1,j+n+1,1,-(val[i]^val[j]));
                    Link(j+n+1,i+1,0,(val[i]^val[j]));
                }
            }
        }
        Cal_MaxFlow_MinCost(S,T,T);
    }
    return 0;
}

HDU 3395 Special Fish 最“大”费用最大流,布布扣,bubuko.com

时间: 2024-10-29 19:08:07

HDU 3395 Special Fish 最“大”费用最大流的相关文章

HDU 3395 Special Fish(拆点+最大费用最大流)

Special Fish Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2367    Accepted Submission(s): 878 Problem Description There is a kind of special fish in the East Lake where is closed to campus o

HDU 3395 Special Fish(费用流)

题目地址:HDU 3395 刷了几道白书和CF上的非算法的智商题,感觉智商越来越接近负数了...还是先刷几道简单题缓缓.. 这题很简单,二分图模型,用费用流也可以,用KM也可以.不过需要注意的是这里是最大费用流,并不是最大费用最大流,区别在于是否是最大流,这题可以不是最大流,所以要当费用开始减少的时候停止继续流,来保证费用是最大的. 代码如下: #include <iostream> #include <cstdio> #include <string> #includ

HDU 3395 Special Fish(最大费用流)

Special Fish Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1814    Accepted Submission(s): 678 Problem Description There is a kind of special fish in the East Lake where is closed to campus o

hdoj 3395 Special Fish 【最大费用流】

Special Fish Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1920    Accepted Submission(s): 717 Problem Description There is a kind of special fish in the East Lake where is closed to campus o

[ACM] HDU 3395 Special Fish (二分图最大权匹配,KM算法)

Special Fish Problem Description There is a kind of special fish in the East Lake where is closed to campus of Wuhan University. It's hard to say which gender of those fish are, because every fish believes itself as a male, and it may attack one of s

HDU 3395 Special Fish【最大权匹配】

题意:最大权匹配 分析:最大全匹配 代码: 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 using namespace std; 5 6 const int maxn = 105; 7 const int INF = 2000000000; 8 9 bool Sx[maxn], Sy[maxn]; 10 int Lx[maxn], Ly[maxn]; 11 int Link[maxn]

HDU3395 Special Fish(最大费用任意流)

题目要的并不是最大匹配下得到的最大的结果. 网上流行的做法是加边.其实,在连续增广的时候求得一个可行流的总费用为负就停止这样就行了. 1 #include<cstdio> 2 #include<cstring> 3 #include<queue> 4 #include<algorithm> 5 using namespace std; 6 #define INF (1<<30) 7 #define MAXN 222 8 #define MAXM

hdu 5352 MZL&#39;s City 最小费用最大流

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5352 题意:M年前有一个国家发生了地震.所有城市和城市之间的路都被摧毁了.现在要重建城市. 给出一个N表示共有N个城市,M表示大地震发生在M年前,K表示每次最多只能重建K个城市. 现在从大地震发生的那年开始,每年可以进行一个操作,也就是总共有M个操作. 1 x表示可以重建和x联通(直接或间接)的城市(包括x本身),每次最多只能重建K个城市 2 x y 表示修建了一条城市x到城市y的路. 3操作给出一

HDU 3376 Matrix Again(最大费用最大流)HDU2686加强题

Matrix Again Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 102400/102400 K (Java/Others) Total Submission(s): 3206    Accepted Submission(s): 937 Problem Description Starvae very like play a number game in the n*n Matrix. A positive integer