您的位置:首页 > 其它

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

2014-07-22 20:49 369 查看
求最大费用可以将边权取负以转化成求最小费用。然而此时依然不对,因为会优先寻找最大流,但是答案并不一定出现在满流的时候。所以要加一些边(下图中的红边)使其在答案出现时满流。设所有边的流量为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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: