bzoj 1497 NOI2006最大获利
2016-12-20 21:30
288 查看
我对题意的理解:给出一堆公司和一堆用户,我们买公司需要花钱,每个用户会支付报酬当且仅当他所钟爱的两个公司我都买了,问最大获利
最大权闭合子图= =好厉害的样子 首先我们连边最小割ans 答案就是sum-ans 这个可以想,sum表示在不需要支出的情况下的获利,现在我们需要支出,所以要跑一遍最小割。感觉就是 我们挣的钱可以通过一个途径跑掉,就挣不到,但是一个途径跑掉的钱是有限的。(怎么会有我这么愚蠢的理解呢) 建立源S,汇T 然后由S向所有用户连长度为报酬的边,用户向喜欢的公司连inf(表示一些疯狂的女人为了买衣服会花好多好多钱),然后公司向汇点连长度为价格的边。看着好奇怪啊,但是我想明白啦!
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<cstdio>
# define inf 1e9
using namespace std;
const int maxn=600000;
struct node{int to,next,len;}table[maxn<<2];
int tot=1,head[maxn];
void add(int a,int b,int c)
{
table[++tot]=(node){b,head[a],c};
head[a]=tot;
table[++tot]=(node){a,head[b],0};
head[b]=tot;
}
int n,m,S,T,a[maxn],ans,sum;
int q[maxn],h,t,d[maxn];
bool bfs()
{
h=t=0;
memset(d,0,sizeof d);
q[++t]=S; d[S]=1;
while(h!=t)
{
int x=q[++h];
for(int i=head[x];i;i=table[i].next)
if(!d[table[i].to]&&table[i].len)
{
d[table[i].to]=d[x]+1;
q[++t]=table[i].to;
}
}
return !!d[T];
}
int dfs(int x,int f)
{
if(x==T||!f) return f;
int cnt=0;
for(int i=head[x];i;i=table[i].next)
if(d[table[i].to]==d[x]+1)
{
int hh=dfs(table[i].to,min(f,table[i].len));
table[i].len-=hh;
table[i^1].len+=hh;
cnt+=hh;
f-=hh;
if(!f) break;
}
return cnt;
}
int main()
{
scanf("%d%d",&n,&m);
S=n+m+1,T=n+m+2;
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
add(m+i,T,a[i]);
}
int a,b,c;
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&a,&b,&c); sum+=c;
add(S,i,c);
add(i,m+a,inf);
add(i,m+b,inf);
}
while(bfs()) ans+=dfs(S,inf);
cout<<sum-ans;
return 0;
}
最大权闭合子图= =好厉害的样子 首先我们连边最小割ans 答案就是sum-ans 这个可以想,sum表示在不需要支出的情况下的获利,现在我们需要支出,所以要跑一遍最小割。感觉就是 我们挣的钱可以通过一个途径跑掉,就挣不到,但是一个途径跑掉的钱是有限的。(怎么会有我这么愚蠢的理解呢) 建立源S,汇T 然后由S向所有用户连长度为报酬的边,用户向喜欢的公司连inf(表示一些疯狂的女人为了买衣服会花好多好多钱),然后公司向汇点连长度为价格的边。看着好奇怪啊,但是我想明白啦!
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<cstdio>
# define inf 1e9
using namespace std;
const int maxn=600000;
struct node{int to,next,len;}table[maxn<<2];
int tot=1,head[maxn];
void add(int a,int b,int c)
{
table[++tot]=(node){b,head[a],c};
head[a]=tot;
table[++tot]=(node){a,head[b],0};
head[b]=tot;
}
int n,m,S,T,a[maxn],ans,sum;
int q[maxn],h,t,d[maxn];
bool bfs()
{
h=t=0;
memset(d,0,sizeof d);
q[++t]=S; d[S]=1;
while(h!=t)
{
int x=q[++h];
for(int i=head[x];i;i=table[i].next)
if(!d[table[i].to]&&table[i].len)
{
d[table[i].to]=d[x]+1;
q[++t]=table[i].to;
}
}
return !!d[T];
}
int dfs(int x,int f)
{
if(x==T||!f) return f;
int cnt=0;
for(int i=head[x];i;i=table[i].next)
if(d[table[i].to]==d[x]+1)
{
int hh=dfs(table[i].to,min(f,table[i].len));
table[i].len-=hh;
table[i^1].len+=hh;
cnt+=hh;
f-=hh;
if(!f) break;
}
return cnt;
}
int main()
{
scanf("%d%d",&n,&m);
S=n+m+1,T=n+m+2;
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
add(m+i,T,a[i]);
}
int a,b,c;
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&a,&b,&c); sum+=c;
add(S,i,c);
add(i,m+a,inf);
add(i,m+b,inf);
}
while(bfs()) ans+=dfs(S,inf);
cout<<sum-ans;
return 0;
}
相关文章推荐
- BZOJ 1497: [NOI2006]最大获利(最大权闭合图)
- 【BZOJ 1497】 [NOI2006]最大获利 最大权闭合子图
- BZOJ 1497: [NOI2006]最大获利( 最大流 )
- bzoj 1497: [NOI2006]最大获利
- bzoj1497【NOI2006】最大获利
- BZOJ 1497 [NOI2006]最大获利(最小割)
- 【NOI2006】BZOJ1497最大获利
- BZOJ 1497: [NOI2006]最大获利 最小割
- 【BZOJ】1497 [NOI2006]最大获利
- bzoj 1497: [NOI2006]最大获利-----------算法模板[最大权闭合子图]&省选计划系列
- BZOJ1497 NOI2006最大获利
- bzoj 1497: [NOI2006]最大获利 -- 最小割
- BZOJ 1497 [NOI2006] 最大获利
- [BZOJ1497][NOI2006]最大获利
- 【BZOJ1497】【NOI2006】最大获利
- [网络流]bzoj1497 [NOI2006]最大获利
- BZOJ 1497 [NOI2006]最大获利 【最大流】
- [BZOJ1497] [NOI2006] 最大获利 - 网络流
- 【bzoj1497】 NOI2006—最大获利
- bzoj 1497: [NOI2006]最大获利(网络流)