【LA3487】最小割-经典模型 两种方法
题意:A、B两个公司要买一些资源(他们自己买的资源不会重复),一个资源只能卖给一个公司。问最大收益。
simple input 部分:
54 1 //买到1就给54元
15 2
33 3
2 4 5//买到4、5就给2元
题解:这道题是很经典的模型题,在这里给出两个方法。
方法一 把每个询问看成一个点,然后A的询问连源点,B的询问连汇点,如果AB间的某个询问有矛盾就在它们中间连一条无限大的边,ans=sum-最小割。
// 方法一 把每个询问看成一个点,然后A的询问连源点,B的询问连汇点,如果AB间的某个
// 询问有矛盾就在它们中间连一条无限大的边,ans=sum-最小割。 #include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<queue>
#include<vector>
using namespace std; const int N=,INF=(int)1e9;
int s,t,len,num;
int first[*N],dis[*N];
int A[N],B[N],p1[N],p2[N];
// bool vis[2*N];
bool vis[][];
struct node{
int x,y,d,next;
}a[*N];
queue<int> q; int minn(int x,int y){return x<y ? x:y;}
int maxx(int x,int y){return x>y ? x:y;} void ins(int x,int y,int d)
{
a[++len].x=x;a[len].y=y;a[len].d=d;
a[len].next=first[x];first[x]=len;
a[++len].x=y;a[len].y=x;a[len].d=;
a[len].next=first[y];first[y]=len;
} bool bfs(int st,int ed)
{
while(!q.empty()) q.pop();
memset(dis,-,sizeof(dis));
dis[st]=;
q.push(st);
while(!q.empty())
{
int x=q.front();q.pop();
for(int i=first[x];i!=-;i=a[i].next)
{
int y=a[i].y;
if(dis[y]==- && a[i].d>)
{
dis[y]=dis[x]+;
q.push(y);
}
}
}
return (dis[ed]!=-);
} int dfs(int x,int ed,int flow)
{
int r=,p;
if(x==ed) return flow;
for(int i=first[x];i!=-;i=a[i].next)
{
int y=a[i].y;
if(dis[y]==dis[x]+ && a[i].d>)
{
p=minn(a[i].d,flow-r);
p=dfs(y,ed,p);
r+=p;
a[i].d-=p;
a[i^].d+=p;
}
}
if(!r) dis[x]=-;
return r;
} int dinic(int st,int ed)
{
int ans=;
while(bfs(st,ed))
{
int p;
while(p=dfs(st,ed,INF)) ans+=p;
}
return ans;
} int main()
{
int T,cas=;
scanf("%d",&T);
while(T--)
{
len=-;
memset(first,-,sizeof(first));
memset(A,,sizeof(A));
memset(B,,sizeof(B));
memset(vis,,sizeof(vis));
int n,m,sum=,mx=,num=;
scanf("%d",&n);
for(int i=;i<=n;i++)
{
scanf("%d",&p1[i]);
sum+=p1[i];
int x;num++;
while()
{
char c;
scanf("%d%c",&x,&c);
A[x]=i;
mx=maxx(mx,x);
if(c=='\n') break;
}
}
scanf("%d",&m);
s=,t=n+m+;
for(int i=;i<=m;i++)
{
scanf("%d",&p2[i]);
sum+=p2[i];num++;
int x;
while()
{
char c;
scanf("%d%c",&x,&c);
B[x]=i;
mx=maxx(mx,x);
if(c=='\n') break;
}
}
for(int i=;i<=n;i++) ins(s,i,p1[i]);
for(int i=;i<=m;i++) ins(i+n,t,p2[i]);
for(int i=;i<=mx;i++)
{
if(!A[i]||!B[i]||vis[A[i]][B[i]]) continue;
vis[A[i]][B[i]]=true;
ins(A[i],B[i]+n,INF);
}
printf("Case %d:\n",++cas);
printf("%d\n",sum-dinic(s,t));
if(T) printf("\n");
}
return ;
}
方法一
方法二:对于每个询问,新建一个点x,如果是A就源点连向这个点,流量为价钱p,然后x连向这个询问所要求买的资源c[i],流量为INF。
如果是B则反过来,连向汇点。

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<queue>
#include<vector>
using namespace std; const int N=,INF=(int)1e9;
int s,t,len,num;
int first[*N],dis[*N];
int A[N],B[N];
bool vis[][];
struct node{
int x,y,d,next;
}a[*N];
queue<int> q; int minn(int x,int y){return x<y ? x:y;}
int maxx(int x,int y){return x>y ? x:y;} void ins(int x,int y,int d)
{
a[++len].x=x;a[len].y=y;a[len].d=d;
a[len].next=first[x];first[x]=len;
a[++len].x=y;a[len].y=x;a[len].d=;
a[len].next=first[y];first[y]=len;
} bool bfs(int st,int ed)
{
while(!q.empty()) q.pop();
memset(dis,-,sizeof(dis));
dis[st]=;
q.push(st);
while(!q.empty())
{
int x=q.front();q.pop();
for(int i=first[x];i!=-;i=a[i].next)
{
int y=a[i].y;
if(dis[y]==- && a[i].d>)
{
dis[y]=dis[x]+;
q.push(y);
}
}
}
return (dis[ed]!=-);
} int dfs(int x,int ed,int flow)
{
int r=,p;
if(x==ed) return flow;
for(int i=first[x];i!=-;i=a[i].next)
{
int y=a[i].y;
if(dis[y]==dis[x]+ && a[i].d>)
{
p=minn(a[i].d,flow-r);
p=dfs(y,ed,p);
r+=p;
a[i].d-=p;
a[i^].d+=p;
}
}
if(!r) dis[x]=-;
return r;
} int dinic(int st,int ed)
{
int ans=;
while(bfs(st,ed))
{
int p;
while(p=dfs(st,ed,INF)) ans+=p;
}
return ans;
} int main()
{
int T,cas=;
scanf("%d",&T);
while(T--)
{
len=-;
memset(first,-,sizeof(first));
memset(A,,sizeof(A));
memset(B,,sizeof(B));
memset(vis,,sizeof(vis));
int n,m,p,sum=,mx=,num=;
scanf("%d",&n);
for(int i=;i<=n;i++)
{
scanf("%d",&p);
sum+=p;
int x;num++;
ins(,num,p);
while()
{
char c;
scanf("%d%c",&x,&c);
ins(num,x+,INF);
if(c=='\n') break;
}
}
scanf("%d",&m);
s=,t=;
for(int i=;i<=m;i++)
{
scanf("%d",&p);
sum+=p;num++;
ins(num,t,p);
int x;
while()
{
char c;
scanf("%d%c",&x,&c);
ins(x+,num,INF);
if(c=='\n') break;
}
}
for(int i=;i<=n;i++) ins(s,i,p1[i]);
for(int i=;i<=m;i++) ins(i+n,t,p2[i]);
for(int i=;i<=mx;i++)
{
if(!A[i]||!B[i]||vis[A[i]][B[i]]) continue;
vis[A[i]][B[i]]=true;
ins(A[i],B[i]+n,INF);
}
printf("Case %d:\n",++cas);
printf("%d\n",sum-dinic(s,t));
if(T) printf("\n");
}
return ;
}
方法二
【LA3487】最小割-经典模型 两种方法的更多相关文章
- 【BZOJ 3232】圈地游戏 二分+SPFA判环/最小割经典模型
最小割经典模型指的是“一堆元素进行选取,对于某个元素的取舍有代价或价值,对于某些对元素,选取后会有额外代价或价值”的经典最小割模型,建立倒三角进行最小割.这个二分是显然的,一开始我也是想到了最小割的那 ...
- 清除SQLServer日志的两种方法
日志文件满而造成SQL数据库无法写入文件时,可用两种方法:一种方法:清空日志.1.打开查询分析器,输入命令DUMP TRANSACTION 数据库名 WITH NO_LOG2.再打开企业管理器--右键 ...
- WebGL中添加天空盒的两种方法
天空盒 的添加可以让模型所在的场景非常漂亮,而其原理也是非常简单的,相信看完下面代码就可以明白了. 说到天空盒的两种方法,倒不如说是两种写法,分别用了纹理加载的两个方法:loadTexture和loa ...
- [转]Delphi调用cmd的两种方法
delphi调用cmd的两种方法vars:string;begins:='cmd.exe /c '+edit1.Text+' >c:\1.txt';winexec(pchar(s),sw_hid ...
- Java学习笔记——可视化Swing中JTable控件绑定SQL数据源的两种方法
在 MyEclipse 的可视化 Swing 中,有 JTable 控件. JTable 用来显示和编辑常规二维单元表. 那么,如何将 数据库SQL中的数据绑定至JTable中呢? 在这里,提供两种方 ...
- 织梦首页、列表页调用文章body内容的两种方法
http://blog.csdn.net/langyu1021/article/details/52261411 关于首页.列表页调用文章body内容的两种方法,具体方法如下: 第一种方法: {ded ...
- 转载]PhpCms V9调用指定栏目子栏目文章的两种方法
PhpCms V9调用指定栏目子栏目文章的两种方法 第一种.直接写子栏目id ,用cat in {pc:get sql="SELECT * from v9_news where status ...
- ZBrush中设置背面遮罩的两种方法
背面遮罩是ZBrush软件实时遮罩的一种,它的出现能够解决我们在模型雕刻时的一些问题.我们在 ZBrush®中雕刻一个比较薄的物体时,经常会不经意的雕刻到背面的物体.那么遇到此类状况该如何设置ZBru ...
- [ARM-Linux开发]Linux下加载.ko驱动模块的两种方法:insmod与modprobe
假设要加载的驱动程序模块名为SHT21.ko 加载驱动模块 方法一: 进入SHT21.ko驱动模块文件所在的目录,然后直接 insmod SHT21.ko 即可 方法二: 将SHT21.ko文 ...
随机推荐
- stm32--USB(作为U盘)+FatFs的实现
一.USB功能的添加(作为U盘) 添加文件 将官方库中的Library文件夹中的所有有效文件添加到工程中,分为4个文件夹: usb class为硬件相关(Library\Class): usb dri ...
- C++语言入门知识点(详细版)【持续更新每周三更】,小舒舒戳这里!!!
时间过得好快啊,LITTLESUN已经在这块新地图摸打滚爬了一个多月了.前一段时间出了点小意外一直没能更新博客,昨天被小舒舒催更了(惭愧惭愧)便准备着手来一篇回忆录回首一下这一个月走过的风风雨雨,也希 ...
- 玩转Vim-札记(一)
玩转Vim-札记(一) 简介 在这个蔚蓝色的星球上,流传着两大神器的传说:据说Emacs是神的编辑器,而Vim是编辑器之神.一些人勇敢地拾起了Vim或Emacs,却发现学习曲线陡峭而漫长,还是有一些人 ...
- ES6 语法糖
重新认识ES6中的语法糖:https://segmentfault.com/a/1190000010159725
- Python 3基础教程20-Python中导入模块和包
本文介绍Python中导入模块和包 #目录: # 导入模块和包--- # | # 上级包.上级模块.导入模块和包的init模块----- # | # 同级包.同级模块.上级包的init模块.test模 ...
- SPRITEKIT游戏框架之关于PHYSICS物理引擎属性
Spritekit提供了一个默认的物理模拟系统,用来模拟真实物理世界,可以使得编程者将注意力从力学碰撞和重力模拟的计算中解放出来,通过简单地代码来实现物理碰撞的模拟,而将注意力集中在更需要花费精力的地 ...
- 51单片机实现外部中断0-F
#include< reg51.h> #define uint unsigned int #define uchar unsigned char sfr P0M0 = 0x94; sfr ...
- Spring Boot 学习随记
微架构的思想在各大互联网公司越来越普及,特此记录Spring Boot的一些细节问题! 网上spring-boot的教程一堆一堆,就没有必要再详细记录了 1:建议通过Idea 来创建spring-bo ...
- laxcus的新功能:支持表跨数据库操作
关系数据库的层次结构,是账号.数据库.表,一个账号下可以有多个数据库,每个数据库有多个表,但是不同数据库下的表是不能够互相操作的.例如:"select a.*, b.* from Title ...
- [Binary Search] Leetcode 35, 74
35. Search Insert Position Description Given a sorted array and a target value, return the index if ...