【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=300100,INF=(int)1e9; int s,t,len,num; int first[2*N],dis[2*N]; int A[N],B[N],p1[N],p2[N]; // bool vis[2*N]; bool vis[3100][3100]; struct node{int x,y,d,next; }a[6*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=0;a[len].next=first[y];first[y]=len; }bool bfs(int st,int ed) {while(!q.empty()) q.pop();memset(dis,-1,sizeof(dis));dis[st]=0;q.push(st);while(!q.empty()){int x=q.front();q.pop();for(int i=first[x];i!=-1;i=a[i].next){int y=a[i].y;if(dis[y]==-1 && a[i].d>0){dis[y]=dis[x]+1;q.push(y);}}}return (dis[ed]!=-1); }int dfs(int x,int ed,int flow) {int r=0,p;if(x==ed) return flow;for(int i=first[x];i!=-1;i=a[i].next){int y=a[i].y;if(dis[y]==dis[x]+1 && a[i].d>0){p=minn(a[i].d,flow-r);p=dfs(y,ed,p);r+=p;a[i].d-=p;a[i^1].d+=p;}}if(!r) dis[x]=-1;return r; }int dinic(int st,int ed) {int ans=0;while(bfs(st,ed)){int p;while(p=dfs(st,ed,INF)) ans+=p;}return ans; }int main() {int T,cas=0;scanf("%d",&T);while(T--){len=-1;memset(first,-1,sizeof(first));memset(A,0,sizeof(A));memset(B,0,sizeof(B));memset(vis,0,sizeof(vis));int n,m,sum=0,mx=0,num=300001;scanf("%d",&n);for(int i=1;i<=n;i++){scanf("%d",&p1[i]);sum+=p1[i];int x;num++;while(1){char c;scanf("%d%c",&x,&c);A[x]=i;mx=maxx(mx,x);if(c=='\n') break;}}scanf("%d",&m);s=0,t=n+m+1;for(int i=1;i<=m;i++){scanf("%d",&p2[i]);sum+=p2[i];num++;int x;while(1){char c;scanf("%d%c",&x,&c);B[x]=i;mx=maxx(mx,x);if(c=='\n') break;}}for(int i=1;i<=n;i++) ins(s,i,p1[i]);for(int i=1;i<=m;i++) ins(i+n,t,p2[i]);for(int i=1;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 0; }
方法一
方法二:对于每个询问,新建一个点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=300100,INF=(int)1e9; int s,t,len,num; int first[2*N],dis[2*N]; int A[N],B[N]; bool vis[3100][3100]; struct node{int x,y,d,next; }a[6*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=0;a[len].next=first[y];first[y]=len; }bool bfs(int st,int ed) {while(!q.empty()) q.pop();memset(dis,-1,sizeof(dis));dis[st]=0;q.push(st);while(!q.empty()){int x=q.front();q.pop();for(int i=first[x];i!=-1;i=a[i].next){int y=a[i].y;if(dis[y]==-1 && a[i].d>0){dis[y]=dis[x]+1;q.push(y);}}}return (dis[ed]!=-1); }int dfs(int x,int ed,int flow) {int r=0,p;if(x==ed) return flow;for(int i=first[x];i!=-1;i=a[i].next){int y=a[i].y;if(dis[y]==dis[x]+1 && a[i].d>0){p=minn(a[i].d,flow-r);p=dfs(y,ed,p);r+=p;a[i].d-=p;a[i^1].d+=p;}}if(!r) dis[x]=-1;return r; }int dinic(int st,int ed) {int ans=0;while(bfs(st,ed)){int p;while(p=dfs(st,ed,INF)) ans+=p;}return ans; }int main() {int T,cas=0;scanf("%d",&T);while(T--){len=-1;memset(first,-1,sizeof(first));memset(A,0,sizeof(A));memset(B,0,sizeof(B));memset(vis,0,sizeof(vis));int n,m,p,sum=0,mx=0,num=300001;scanf("%d",&n);for(int i=1;i<=n;i++){scanf("%d",&p);sum+=p;int x;num++;ins(0,num,p);while(1){char c;scanf("%d%c",&x,&c);ins(num,x+1,INF);if(c=='\n') break;}}scanf("%d",&m);s=0,t=1;for(int i=1;i<=m;i++){scanf("%d",&p);sum+=p;num++;ins(num,t,p);int x;while(1){char c;scanf("%d%c",&x,&c);ins(x+1,num,INF);if(c=='\n') break;}}for(int i=1;i<=n;i++) ins(s,i,p1[i]);for(int i=1;i<=m;i++) ins(i+n,t,p2[i]);for(int i=1;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 0; }
方法二
转载于:https://www.cnblogs.com/KonjakJuruo/p/5516479.html
【LA3487】最小割-经典模型 两种方法相关推荐
- 牛客 Tree(最小深度总和)(两种方法求重心)难度⭐⭐⭐
题目链接 牛妹有一张连通图,由n个点和n-1条边构成,也就是说这是一棵树,牛妹可以任意选择一个点为根,根的深度deprootdep_{root}deproot为0,对于任意一个非根的点,我们将他到 ...
- 水平集方法引入主动轮廓模型算法中的两种方法
水平集方法引入主动轮廓模型算法中的两种方法 1.传统的基于主动轮廓模型和水平集理论的方法 2.变分水平集方法 在讲解水平集理论在主动轮廓模型中的应用前,我们先用流程图说明一下常见的处理主动轮廓模型的流 ...
- DL之DNN:自定义2层神经网络TwoLayerNet模型(计算梯度两种方法)利用MNIST数据集进行训练、预测
DL之DNN:自定义2层神经网络TwoLayerNet模型(计算梯度两种方法)利用MNIST数据集进行训练.预测 导读 利用python的numpy计算库,进行自定义搭建2层神经网络TwoLayerN ...
- 加载dict_PyTorch 7.保存和加载pytorch模型的两种方法
众所周知,python的对象都可以通过torch.save和torch.load函数进行保存和加载(不知道?那你现在知道了(*^_^*)),比如: x1 = {"d":" ...
- ML:模型训练/模型评估中常用的两种方法代码实现(留一法一次性切分训练和K折交叉验证训练)
ML:模型训练/模型评估中常用的两种方法代码实现(留一法一次性切分训练和K折交叉验证训练) 目录 模型训练评估中常用的两种方法代码实现 T1.留一法一次性切分训练 T2.K折交叉验证训 模型训练评估中 ...
- [转]快速清除SQL Server日志的两种方法
日志文件满而造成SQL数据库无法写入文件时,可用两种方法: 第一种方法:清空日志. 1.打开查询分析器,输入命令 以下是引用片段: DUMP TRANSACTION 数据库名 WITH NO_LOG ...
- 计算机视觉之人脸识别(Yale数据集)--HOG和ResNet两种方法实现
1.问题描述 在给定Yale数据集上完成以下工作:在给定的人脸库中,通过算法完成人脸识别,算法需要做到能判断出测试的人脸是否属于给定的数据集.如果属于,需要判断出测试的人脸属于数据集中的哪一位.否则, ...
- 命名实体识别python_命名实体识别的两种方法
作者 | Walker [磐创AI导读]:本文主要介绍自然语言处理中的经典问题--命名实体识别的两种方法. 目录 一.什么是命名实体识别 二.基于NLTK的命名实体识别 三.基于Stanford的NE ...
- bufferedreader读取中文乱码_Python读取excel的两种方法
excel是什么 Microsoft Excel是一个使用非常广泛的电子表格程序.它的用户友好性和吸引人的功能使其成为数据科学中常用的工具.对于excel来说,整个excel文件称为工作簿,工作簿中的 ...
最新文章
- oracle 事务故障,处理Oracle的分布式事务故障
- python获取计算机信息系统数据罪_工作心得:破坏计算机信息系统罪与非法获取计算机信息系统数据罪的区分...
- java 正则表达式 替换字符串img标签的路径_python面试题汇总第06期-正则表达式(内附7题及答案)...
- SpringBoot的yml配置文件
- matlab 函数return_基于MATLAB的指纹识别系统【论文,GUI】
- E24- please install the following Perl modules before executing ./mysql_install_db
- Objective-C 协议(protocol)
- jbpm hibernate.cfg.xml 连接mysql配置_hibernate.cfg.xml文件连接mySql、Oracle、SqlServer配置...
- Luogu1091 合唱队形
- 微信小程序数据拼接_微信小程序字符串和变量如何拼接
- 国内电影下载网站收集
- html加载fbx模型,[Unity菜鸟] FBX模型动画提取
- u盘文件夹变成应用程序怎么恢复?方法来了!
- C++(常函数、常对象)
- qt中二维数组的使用_文件数据通过qt将二维数组中的像素点显示成一张图片
- 每日一句: I don't think it's necessary for you to give up
- 快捷键大全---windows , idea , linux , 浏览器
- 三年时间做到年薪百万,推荐明哥的职场心得
- SpringCloud精讲课件(内附源码)
- Python--总结第一阶段