您的位置:首页 > 理论基础 > 计算机网络

【网络流之最大权闭包专题】解题报告

2013-10-02 19:09 281 查看
最大权闭包模型中源点与正收益的点连边,负收益的点与汇点连边,容量取绝对值,然后相关联的点之间之间连容量为无穷大的边。

具体可参见胡伯涛:《最小割模型在信息学竞赛中的应用》

HDU 3061 Battle

  应该是最裸的最大权闭包题了。

#include <vector>
#include <list>
#include <map>
#include <set>
#include <queue>
#include <deque>
#include <stack>
#include <algorithm>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <queue>
using namespace std;
#define pii         pair<LL,LL>
#define clr(a)      memset((a),0,sizeof (a))
#define rep(i,a,b)  for(LL i=(a);i<=(LL)(b);i++)
#define per(i,a,b)  for(LL i=(a);i>=(LL)(b);i--)
#define oo          ((LL)2000000007)*((LL)2000000007)
#define eps         1e-6
#define MAXN        5005
#define MAXM        2000005
#define MOD         1000000007
#define debug       puts("reach here")
#define MP          make_pair
#define PB          push_back
#define RI(x)       scanf("%lld",&x)
#define RII(x,y)    scanf("%lld%lld",&x,&y)
#define RIII(x,y,z) scanf("%d%d%d",&x,&y,&z)
typedef long long LL;

struct Edge
{
LL u, v, next;
LL w;
}E[MAXM];

LL gap[MAXN], pre[MAXN], cur[MAXN], dis[MAXN];
LL n, m;
LL N;
LL head[MAXN], NE;
bool vis[MAXN];

void add_edge (LL u, LL v, LL w)
{
E[NE].u = u; E[NE].v = v; E[NE].w = w; E[NE].next = head[u]; head[u] = NE++;
E[NE].u = v; E[NE].v = u; E[NE].w = 0; E[NE].next = head[v]; head[v] = NE++;
}

inline void checkmin(LL &a,LL b)  {if(a == -1 || a > b)a = b;}

LL sap(LL s,LL t)
{
clr(dis); clr(gap);
for(LL i=0;i<N;++i) cur[i]=head[i];
LL u=pre[s]=s;
LL maxflow=0;
LL aug=-1;
gap[0]=N;
while(dis[s]<N)
{
loop:for(LL &i=cur[u];i!=-1;i=E[i].next)
{
LL v=E[i].v;
if(E[i].w && dis[u]==dis[v]+1)
{
checkmin(aug,E[i].w);
pre[v]=u;
u=v;
if(v==t)
{
maxflow += aug;
for(u=pre[u];v!=s;v=u,u=pre[u])
{
E[cur[u]].w-=aug;
E[cur[u]^1].w+=aug;
}
aug=-1;
}
goto loop;
}
}
LL mindis=N;
for(LL i=head[u];i!=-1;i=E[i].next)
{
LL v=E[i].v;
if(E[i].w && mindis>dis[v])
{
cur[u]=i;
mindis=dis[v];
}
}
if((--gap[dis[u]])==0) break;
gap[dis[u]=mindis+1]++;
u=pre[u];
}
return maxflow;
}

void init()
{
NE = 0;
memset(head, -1, sizeof head);
}

int main()
{
LL a, k;
LL sum, v;
LL M = 5000;
while(scanf("%lld%lld", &n, &m) != EOF)
{
init();
LL s = 0, t = n + m + 1;
sum = 0;
N = t + 1;
rep(i,1,n)
{
scanf("%lld", &v);
add_edge(s, i, v*M+1);
sum += v;
}
rep(i,1,m)
{
scanf("%lld", &v);
if(v > 0)
{
sum += v;
add_edge(s, i+n, v*M);
}
else
add_edge(i+n, t, -v*M);
}
rep(i,1,n)
{
scanf("%lld", &k);
rep(j,1,k)
{
scanf("%lld", &a);
add_edge(i, a+n, oo);
}
}
LL ans = sap(s, t);
printf("%lld %lld\n", sum - ans/M, n - (ans%M));
}
return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: