题目链接

题意: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】最小割-经典模型 两种方法的更多相关文章

  1. 【BZOJ 3232】圈地游戏 二分+SPFA判环/最小割经典模型

    最小割经典模型指的是“一堆元素进行选取,对于某个元素的取舍有代价或价值,对于某些对元素,选取后会有额外代价或价值”的经典最小割模型,建立倒三角进行最小割.这个二分是显然的,一开始我也是想到了最小割的那 ...

  2. 清除SQLServer日志的两种方法

    日志文件满而造成SQL数据库无法写入文件时,可用两种方法:一种方法:清空日志.1.打开查询分析器,输入命令DUMP TRANSACTION 数据库名 WITH NO_LOG2.再打开企业管理器--右键 ...

  3. WebGL中添加天空盒的两种方法

    天空盒 的添加可以让模型所在的场景非常漂亮,而其原理也是非常简单的,相信看完下面代码就可以明白了. 说到天空盒的两种方法,倒不如说是两种写法,分别用了纹理加载的两个方法:loadTexture和loa ...

  4. [转]Delphi调用cmd的两种方法

    delphi调用cmd的两种方法vars:string;begins:='cmd.exe /c '+edit1.Text+' >c:\1.txt';winexec(pchar(s),sw_hid ...

  5. Java学习笔记——可视化Swing中JTable控件绑定SQL数据源的两种方法

    在 MyEclipse 的可视化 Swing 中,有 JTable 控件. JTable 用来显示和编辑常规二维单元表. 那么,如何将 数据库SQL中的数据绑定至JTable中呢? 在这里,提供两种方 ...

  6. 织梦首页、列表页调用文章body内容的两种方法

    http://blog.csdn.net/langyu1021/article/details/52261411 关于首页.列表页调用文章body内容的两种方法,具体方法如下: 第一种方法: {ded ...

  7. 转载]PhpCms V9调用指定栏目子栏目文章的两种方法

    PhpCms V9调用指定栏目子栏目文章的两种方法 第一种.直接写子栏目id ,用cat in {pc:get sql="SELECT * from v9_news where status ...

  8. ZBrush中设置背面遮罩的两种方法

    背面遮罩是ZBrush软件实时遮罩的一种,它的出现能够解决我们在模型雕刻时的一些问题.我们在 ZBrush®中雕刻一个比较薄的物体时,经常会不经意的雕刻到背面的物体.那么遇到此类状况该如何设置ZBru ...

  9. [ARM-Linux开发]Linux下加载.ko驱动模块的两种方法:insmod与modprobe

    假设要加载的驱动程序模块名为SHT21.ko 加载驱动模块 方法一:  进入SHT21.ko驱动模块文件所在的目录,然后直接  insmod SHT21.ko  即可 方法二:  将SHT21.ko文 ...

随机推荐

  1. NOI2018 游记

    day-2 飞向长沙 上午收拾了收拾东西,下载了动画<爱吃拉面的小泉同学>的前五集. 吃过午饭,就准备坐车去运城机场.高铁飞速,转眼间就到了.我没坐过几次飞机,而且比较恐飞,就很难受qwq ...

  2. spring mvc 返回xml格式数据

    1.问题 : 因为业务需要,需要发送xml格式的数据,使用spring mvc 自己解析,就不用费心去自己搞这些东西. 2.解决: 新建一个实体类,直接在实体类中添加注解即可,如下: @XmlRoot ...

  3. 「暑期训练」「基础DP」FATE(HDU-2159)

    题意与分析 学习本题的时候遇到了一定的困难.看了题解才知道这是二重背包.本题的实质是二重完全背包.二维费用的背包问题是指:对于每件物品,具有两种不同的费用,选择这件物品必须同时付出这两种代价:对于每种 ...

  4. Fiddler 4 实现手机App的抓包

    Fiddler不但能截获各种浏览器发出的HTTP请求, 也可以截获各种智能手机发出的HTTP/HTTPS请求. Fiddler能捕获IOS设备发出的请求,比如IPhone, IPad, MacBook ...

  5. Windows系统的高效使用

    1-WIndows10系统的入门使用 2-如何把系统盘的用户文件转移到其他盘 3-Windows装机软件一般有哪些? 4-Windows系统有哪些比较好用的下载器? 5-Windows系统中的播放器 ...

  6. Node.js的require()的工作原理

    大多数人都知道Node.js中require()函数做什么的,但是有多少人知道它的工作原理呢?我们每天使用它加载库包和模块,但是它的内部行为原理很神秘. 我们追寻Node模块系统的核心: module ...

  7. 【转】webpack4

    1.不再支持node.js4.X 2.不能用webpack命令直接打包指定的文件,只能使用webpack.config.js进行配置. 即:webpack  demo01.js  bundle01.j ...

  8. 修改freemarker的ftl时,不重启tomcat的办法(使用了springMVC)

    一.在使用Freemarker 时,需要在spring-mvc.xml 配置文件中作如下配置: <!-- 配置freeMarker的模板路径 --> <bean id="f ...

  9. python 生成csv乱码问题解决方法

    需求背景 最近为公司开发了一套邮件日报程序,邮件一般就是表格,图片,然后就是附件.附件一般都是默认写到txt文件里,但是PM希望邮件里的附件能直接用Excel这种软件打开,最开始想保存为Excel,但 ...

  10. unity 归纳

    1.获取控件四个角在屏幕上的坐标 Vector3[] corners = new Vector3[]; gameObject.GetComponent<RectTransform>().G ...