POJ1087DFS+匈牙利或者DINIC
题意:
有n个插孔,m个电器,q种转换器(转换器可以无限用),然后问你最多有多少个电器能充电。
思路:
比较简单,就是在建图的时候要考虑下,我用了两种方法做的,一个是最大流,这个方法我的建图是这样,先给每个用电器虚拟出来一个点n,每个插座虚拟出来两个点(限流)m,然后给每个插座或者是插头的类型虚拟出来一个点,这样就ok了,建图是这样
s -> 所有用电器 1
所有用电器->他所连接的种类 1
种类 ->种类 INF 这个是转换器
种类 ->插座 1
插座到 ->插座 1 限流
插座 -> t 1
然后一遍s到t的最大流
另一种方法是用二分匹配,这个方法我们可以这样想,建立二分图,左边是用电器,右边是插座,然后用电器和插座能连的条件是可以直接或者间接连接上,这个地方可以用搜索搞定,这样在处理所有连接关系的时候的时间复杂度一共是n^2的,一开始想用Floyd了,考虑到那样的话最坏的情况会达到500*500*500就没用,通过搜索建立间接之后就可以直接匈牙利匹配了,下面是两种方法的代码。
DINIC
#include<map>
#include<queue>
#include<stdio.h>
#include<string>
#include<string.h>
#define N_node 700 + 10
#define N_edge 700 * 700 + 50
#define INF 1000000000
using namespace std;
typedef struct
{
int to ,cost ,next;
}STAR;
typedef struct
{
int x ,t;
}DEP;
STAR E[N_edge];
DEP xin ,tou;
map<string ,int>mark;
int deep[N_node];
int list[N_node] ,listt[N_node] ,tot;
void add(int a ,int b ,int c)
{
E[++tot].to = b;
E[tot].cost = c;
E[tot].next = list[a];
list[a] = tot;
E[++tot].to = a;
E[tot].cost = 0;
E[tot].next = list[b];
list[b] = tot;
}
int minn(int x ,int y)
{
return x < y ? x : y;
}
bool BFS_DEEP(int s ,int t ,int n)
{
memset(deep ,255 ,sizeof(deep));
xin.x = s ,xin.t = 0;
queue<DEP>q;
q.push(xin);
deep[s] = 0;
while(!q.empty())
{
tou = q.front();
q.pop();
for(int k = list[tou.x] ;k ;k = E[k].next)
{
xin.x = E[k].to;
xin.t = tou.t + 1;
if(deep[xin.x] != -1 || !E[k].cost)
continue;
deep[xin.x] = xin.t;
q.push(xin);
}
}
for(int i = 0 ;i <= n ;i ++)
listt[i] = list[i];
return deep[t] != -1;
}
int DFS_Flow(int s ,int t ,int flow)
{
if(s == t) return flow;
int nowflow = 0;
for(int k = listt[s] ;k ;k = E[k].next)
{
listt[s] = k;
int to = E[k].to ,c = E[k].cost;
if(!c || deep[to] != deep[s] + 1)
continue;
int tmp = DFS_Flow(to ,t ,minn(c ,flow - nowflow));
nowflow += tmp;
E[k].cost -= tmp;
E[k^1].cost += tmp;
if(flow == nowflow)
break;
}
if(!nowflow) deep[s] = 0;
return nowflow;
}
int DINIC(int s ,int t ,int n)
{
int ans = 0;
while(BFS_DEEP(s ,t ,n))
{
ans += DFS_Flow(s ,t ,INF);
}
return ans;
}
int main ()
{
int n ,m ,q ,i;
char str1[25+5] ,str2[25+5];
while(~scanf("%d" ,&n))
{
memset(list ,0 ,sizeof(list));
tot = 1;
mark.clear();
int nowid = 0;
int s = 0 ,t = 705;
for(i = 1 ;i <= n ;i ++)
{
scanf("%s" ,str1);
if(!mark[str1]) mark[str1] = ++nowid;
add(mark[str1] + 200 ,mark[str1] + 600 ,1);
add(mark[str1] + 600 ,i + 100 ,1);
add(i + 100 ,t ,1);
}
scanf("%d" ,&m);
for(i = 1 ;i <= m ;i ++)
{
scanf("%s %s" ,str1 ,str2);
if(!mark[str2]) mark[str2] = ++nowid;
add(s ,i ,1);
add(i ,mark[str2] + 200 ,1);
}
scanf("%d" ,&q);
for(i = 1 ;i <= q ;i ++)
{
scanf("%s %s" ,str1 ,str2);
if(!mark[str1]) mark[str1] = ++nowid;
if(!mark[str2]) mark[str2] = ++nowid;
add(mark[str1] + 200 ,mark[str2] + 200 ,INF);
}
printf("%d\n" ,m - DINIC(s ,t ,705));
}
return 0;
}
匈牙利+DFS
#include<map>
#include<stdio.h>
#include<string>
#include<string.h>
#define N_node 500
#define N_edge 500 * 500 + 10
#define INF 100000000
using namespace std;
typedef struct
{
int to ,next;
}STAR;
STAR E[N_edge];
int mkdfs[N_node] ,mkgx[N_node];
int list[N_node] ,tot;
int _map[N_node][N_node];
int cz[N_node] ,dq[N_node];
map<string ,int>mark;
void add(int a ,int b)
{
E[++tot].to = b;
E[tot].next = list[a];
list[a] = tot;
}
void DFS(int s ,int now)
{
for(int k = list[now] ;k ;k = E[k].next)
{
int to = E[k].to;
if(mkdfs[to]) continue;
mkdfs[to] = _map[s][to] = 1;
DFS(s ,to);
}
return ;
}
int DFS_XYL(int x)
{
for(int k = list[x] ;k ;k = E[k].next)
{
int to = E[k].to;
if(mkdfs[to]) continue;
mkdfs[to] = 1;
if(mkgx[to] == -1 || DFS_XYL(mkgx[to]))
{
mkgx[to] = x;
return 1;
}
}
return 0;
}
int main ()
{
int n ,m ,q ,i ,j ,a ,b;
char str1[30] ,str2[30];
while(~scanf("%d" ,&n))
{
mark.clear();
int nowid = 0;
for(i = 1 ;i <= n ;i ++)
{
scanf("%s" ,str1);
if(!mark[str1]) mark[str1] = ++nowid;
cz[i] = mark[str1];
}
scanf("%d" ,&m);
for(i = 1 ;i <= m ;i ++)
{
scanf("%s %s" ,str1 ,str2);
if(!mark[str2]) mark[str2] = ++nowid;
dq[i] = mark[str2];
}
memset(list ,0 ,sizeof(list));
tot = 1;
scanf("%d" ,&q);
for(i = 1 ;i <= q ;i ++)
{
scanf("%s %s" ,str1 ,str2);
if(!mark[str1]) mark[str1] = ++nowid;
if(!mark[str2]) mark[str2] = ++nowid;
add(mark[str1] ,mark[str2]);
}
memset(_map ,0 ,sizeof(_map));
for(i = 1 ;i <= nowid ;i ++)
{
memset(mkdfs ,0 ,sizeof(mkdfs));
_map[i][i] = 1;
DFS(i ,i);
}
memset(list ,0 ,sizeof(list));
tot = 1;
for(i = 1 ;i <= m ;i ++)
for(j = 1 ;j <= n ;j ++)
if(_map[dq[i]][cz[j]]) add(i ,j);
int ans = 0;
memset(mkgx ,255 ,sizeof(mkgx));
for(i = 1 ;i <= nowid ;i ++)
{
memset(mkdfs ,0 ,sizeof(mkdfs));
ans += DFS_XYL(i);
}
printf("%d\n" ,m - ans);
}
return 0;
}
POJ1087DFS+匈牙利或者DINIC的更多相关文章
- 二分图最大匹配模板【匈牙利;Dinic最大流】
二分图最大匹配模板[匈牙利:Dinic最大流] 匈牙利算法 int n,m; vector<int> map[100010]; int match[100010];//保存匹配的互相点 b ...
- 【题解】Uoj79一般图最大匹配
带花树裸题,感觉带花树强强……不会的勿看此文,解释的可能不对,只是给自己看的!!!如题,带花树即为求一般图最大匹配算法(匈牙利与dinic为二分图最大匹配).推荐论文:2015年<浅谈图的匹配算 ...
- 【二分】【字符串哈希】【二分图最大匹配】【最大流】XVII Open Cup named after E.V. Pankratiev Stage 14, Grand Prix of Tatarstan, Sunday, April 2, 2017 Problem I. Minimum Prefix
给你n个字符串,问你最小的长度的前缀,使得每个字符串任意循环滑动之后,这些前缀都两两不同. 二分答案mid之后,将每个字符串长度为mid的循环子串都哈希出来,相当于对每个字符串,找一个与其他字符串所选 ...
- 【bzoj2044】三维导弹拦截 dp+二分图最大匹配
题目描述 n个物品,第i个位置有ai.bi.ci三种属性.每次可以选出满足$\ a_{p_i}<a_{p_{i+1}}\ ,\ b_{p_i}<b_{p_{i+1}}\ ,\ c_{p_i ...
- [bzoj2150]部落战争_二分图最小路径覆盖
部落战争 bzoj-2150 题目大意:题目链接. 注释:略. 想法: 显然是最小路径覆盖,我们知道:二分图最小路径覆盖等于节点总数-最大匹配. 所以我们用匈牙利或者dinic跑出最大匹配,然后用总结 ...
- 网络流基础&网络流24题
网络最大流 dinic+当前弧优化. const int N=10007,M=100007,inf=1e9; int s,t,head[N],ver[M],edge[M],Next[M],tot=1, ...
- SDOI2018凉凉记
好久没有更博客了...因为我在颓废学习.. SDOI一轮结束了...我也该回来学地生了... 凉凉 ————————————————我是分割线———————————————— Day0 愉快感冒的Da ...
- luogu3386 【模板】二分图匹配 匈牙利算法 hdu2063 过山车 dinic
luogu 匈牙利算法 #include <iostream> #include <cstring> #include <cstdio> using namespa ...
- Bzoj 2718: [Violet 4]毕业旅行 && Bzoj 1143: [CTSC2008]祭祀river 传递闭包,二分图匹配,匈牙利,bitset
1143: [CTSC2008]祭祀river Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1878 Solved: 937[Submit][St ...
随机推荐
- vs2019远程调试
VS2019远程调试 这几天遇到个很是纠结的问题,同样的源代码,放在测试服务器,完美运行.但是上线正式环境就是死活显示不出来.于是想到了微软的远程调试功能,这里用VS2019举例. 下载远程访问工具 ...
- 干货满满-原来这才是hooks-React Hooks使用心得
序言 ---最后有招聘信息哦-React是一个库,它不是一个框架.用于构建用户界面的Javascript库.这里大家需要认识这一点.react的核心在于它仅仅是考虑了如何将dom节点更快更好更合适的渲 ...
- Mysql在windows环境如何修改密码?
1.关闭正在运行的MySQL服务. 2. 打开DOS窗口,转到mysql\bin目录. 3. 输入mysqld --skip-grant-tables 回车.--skip-grant-tables 的 ...
- 分形、分形几何、数据可视化、Python绘图
本系列采用turtle.matplotlib.numpy这三个Python工具,以分形与计算机图像处理的经典算法为实例,通过程序和图像,来帮助读者一步步掌握Python绘图和数据可视化的方法和技巧,并 ...
- 【数据结构与算法】——链表(Linked List)
链表(Linked List)介绍 链表是有序的列表,但是它在内存中是存储如下: 链表是以节点的方式来存储的,是链式存储. 每个节点包含data域,next域:指向下一个节点. 如图:链表的各个节点不 ...
- ApiTesting全链路接口自动化测试框架 - 实战应用
场景一.添加公共配置 我们在做自动化开始的时候,一般有很多公共的环境配置,比如host.token.user等等,如果这些放在用例中,一旦修改,将非常的不便.麻烦(尤其切换环境). 所以这里我们提供了 ...
- 博文推荐|多图详解 Apache Pulsar 消息存储模型
关于 Apache Pulsar Apache Pulsar 是 Apache 软件基金会顶级项目,是下一代云原生分布式消息流平台,集消息.存储.轻量化函数式计算为一体,采用计算与存储分离架构设计,支 ...
- .net 预处理指令符的使用
目录 什么是预处理指令符? 预处理指令符的使用 自定义指令符 使用Visual Studio快速定义指令符 定义指令符区域 什么是预处理指令符? 当C#编译器找到一条预处理指令#if,最后找到一条指令 ...
- [Fundamental of Power Electronics]-PART I-6.变换器电路-6.2 变换器简单罗列
6.2 变换器简单罗列 变换器的数量可能有无穷种,因此将其全部列出是不可能的.这里给出了一个简单的罗列清单. 首先考虑含单个电感的单输入单输出变换器的类别.可以在电源和负载之间进行连接电感的方法数量是 ...
- ASP.NET Core中使用令牌桶限流
在限流时一般会限制每秒或每分钟的请求数,简单点一般会采用计数器算法,这种算法实现相对简单,也很高效,但是无法应对瞬时的突发流量. 比如限流每秒100次请求,绝大多数的时间里都不会超过这个数,但是偶尔某 ...