codeforces847J Students Initiation 网络流
题意:
有n个人,m对关系,要求每对关系中,有且仅有一个人给另外一个人送礼物,并且使送出礼物最多的人送的礼物尽可能少。并输出送礼物的方案。
思路:这道题麻烦的是网络流模型的转换(废话)。
最关键的因素是每对关系中只有一个人能给另外一个人送礼物,也就是说是不能相互送礼物的,虽然这句话是废话,但是正因为如此,如果我们考虑直接按照人建点,最后的方案会有问题。(流量相同,但方案错误)。
#pragma GCC optimize (2)
#pragma G++ optimize (2)
#pragma comment(linker, "/STACK:102400000,102400000")
#include<bits/stdc++.h>
#include<cstdio>
#include<vector>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define dep(i,b,a) for(int i=b;i>=a;i--)
#define clr(a,b) memset(a,b,sizeof(a))
#define pb push_back
#define pii pair<int,int >
using namespace std;
typedef long long ll;
const int maxn=;
const int inf=0x3f3f3f3f;
ll rd()
{
ll x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
const ll INFLL = 0x3f3f3f3f3f3f3f3f;
const int INF = 0x3f3f3f3f; struct Edge {
int to, flow, nxt;
Edge() {}
Edge(int to, int nxt, int flow):to(to),nxt(nxt), flow(flow) {}
} edge[maxn << ]; int head[maxn], dep[maxn];
int S, T;
int N, n, m, tot,cnt;
vector<pair<int,int> >va;
void Init(int n) {
N = n;
for (int i = ; i <= N; ++i) head[i] = -;
tot = ;
} void addv(int u, int v, int w, int rw = ) {
edge[tot] = Edge(v, head[u], w);
head[u] = tot++;
edge[tot] = Edge(u, head[v], rw);
head[v] = tot++;
} bool BFS() {
for (int i = ; i <= N; ++i) dep[i] = -;
queue<int>q;
q.push(S);
dep[S] = ;
while (!q.empty()) {
int u = q.front();
q.pop();
for (int i = head[u]; ~i; i = edge[i].nxt) {
if (edge[i].flow && dep[edge[i].to] == -) {
dep[edge[i].to] = dep[u] + ;
q.push(edge[i].to);
}
}
}
return dep[T] < ? : ;
} int DFS(int u, int f) {
if (u == T || f == ) return f;
int w, used = ;
for (int i = head[u]; ~i; i = edge[i].nxt) {
if (edge[i].flow && dep[edge[i].to] == dep[u] + ) {
w = DFS(edge[i].to, min(f - used, edge[i].flow));
edge[i].flow -= w;
edge[i ^ ].flow += w;
used += w;
if (used == f) return f;
}
}
if (!used) dep[u] = -;
return used;
} int Dicnic() {
int ans = ;
while (BFS()) {
ans += DFS(S, INF);
}
return ans;
}
int vs[][];
bool check(int res){
Init(T);
rep(i,,m){
addv(i+n,T,);
}
rep(i,,n){
addv(S,i,res);
}
rep(i,,m-){
int u=va[i].first,v=va[i].second;
addv(u,i++n,);
addv(v,i++n,);
}
int flow=Dicnic();
if(flow>=m){
return true;
}
return false;
} int main() {
while (~scanf("%d %d", &n, &m)) {
va.clear();
S = , T = n+m+;
rep(i,,m){
int u,v;
scanf("%d%d",&u,&v);
va.push_back({u,v});
}
int l=,r=n+,mid,ans=-;
while(l<=r){
mid=(l+r)>>;
if(check(mid)){
ans=mid;
r=mid-;
}else{
l=mid+;
}
} check(ans);
printf("%d\n", ans);
int flow=Dicnic();
for(int u=;u<=n;u++){
for(int i=head[u];i!=-;i=edge[i].nxt){ if(edge[i].flow==&&edge[i].to>n){
int id=edge[i].to-n;
int x= (va[id-].first==u?va[id-].second:va[id-].first);
printf("%d %d\n",u,x);
}
}
}
}
}
所以我们要考虑建立n个点,每个点对应一个人,再建立m个点,每个点对应一对关系,每个关系向汇点连一条容量为1的边,每个人向自己所处的所有关系都连容量为1的边,这样就使得上面说的这个条件成立了。然后我们就建立虚拟源点,二分每个源点向人的流量,每次重新建图即可。
最后输出方案,每个点流出的容量为0的边就是方案。
codeforces847J Students Initiation 网络流的更多相关文章
- 2017-2018 ACM-ICPC, NEERC, Southern Subregional Contest, qualification stage
2017-2018 ACM-ICPC, NEERC, Southern Subregional Contest, qualification stage A. Union of Doubly Link ...
- Codeforces 最大流 费用流
这套题目做完后,一定要反复的看! 代码经常出现的几个问题: 本机测试超时: 1.init函数忘记写. 2.addedge函数写成add函数. 3.边连错了. 代码TLE: 1.前向星边数组开小. 2. ...
- SGU 242. Student's Morning( 网络流 )
看英文题真是麻烦...理解题意花的时间比想的时间还长...裸的网络流, 我们只要限制每个人出发流量为1, 每个大学进入的流量至多为2即可, 相当于构造可行解. -------------------- ...
- plain framework 1 网络流 缓存数据详解
网络流是什么?为什么网络流中需要存在缓存数据?为什么PF中要采用缓存网络数据的机制?带着这几个疑问,让我们好好详细的了解一下在网络数据交互中我们容易忽视以及薄弱的一块.该部分为PF现有的网络流模型,但 ...
- 网络流模板 NetworkFlow
身边的小伙伴们都在愉快地刷网络流,我也来写一发模板好了. Network Flow - Maximum Flow Time Limit : 1 sec, Memory Limit : 65536 KB ...
- COGS732. [网络流24题] 试题库
«问题描述:假设一个试题库中有n道试题.每道试题都标明了所属类别.同一道题可能有多个类别属性.现要从题库中抽取m 道题组成试卷.并要求试卷包含指定类型的试题.试设计一个满足要求的组卷算法.«编程任务: ...
- ACM/ICPC 之 有流量上下界的网络流-Dinic(可做模板)(POJ2396)
//有流量上下界的网络流 //Time:47Ms Memory:1788K #include<iostream> #include<cstring> #include<c ...
- BZOJ 3144 [Hnoi2013]切糕 ——网络流
[题目分析] 网络流好题! 从割的方面来考虑问题往往会得到简化. 当割掉i,j,k时,必定附近的要割在k-D到k+D上. 所以只需要建两条inf的边来强制,如果割不掉强制范围内的时候,原来的边一定会换 ...
- bzoj3572又TM是网络流
= =我承认我写网络流写疯了 = =我承认前面几篇博文都是扯淡,我写的是垃圾dinic(根本不叫dinic) = =我承认这道题我调了半天 = =我承认我这道题一开始是T的,后来换上真正的dinic才 ...
随机推荐
- Web前端基础学习-3
bfc(block formatting context) 块级格式化上下文 生成bfc的方式: 1.根元素: 2.float属性不为none(脱离文档流): 3.position为absolute或 ...
- android jni控制gpio (rk3288)
1.添加驱动程序 2.编写jni c程序编译为库给java调用 3.app调用jni静态链接库操作底层驱动 1.添加驱动程序 修改/work/rk3288/firefly-rk3288_android ...
- Java 枚举和类的区别
枚举 包含一组常量合法的数据,不能创建枚举实例,也不能进行扩展. package com.jtfr.demo; public enum Week { MONDAY, TUESDAY, WEDNESDA ...
- Hibernate中Session的save()、update()、merge()、lock()、saveOrUpdate()和persist()方法有什么区别?
Hibernate的对象有三种状态:瞬态.持久态和游离态.游离状态的实例可以通过调用save().persist()或者saveOrUpdate()方法进行持久化:脱管状态的实例可以通过调用 upda ...
- vue 点击当前元素改变样式
template <ul> <li v-for="(relation,index) in relations" v-bind:id="relat ...
- Vue.js(六)
路由(用 Vue.js + Vue Router 创建单页应用) <script src="https://unpkg.com/vue-router/dist/vue-router.j ...
- SQL Wildcards 通配符
SQL Wildcards通配符 通配符用于替换字符串中的任何其他字符. 通配符与SQL LIKE运算符一起使用.在WHERE子句中使用LIKE运算符来搜索列中的指定模式. 有两个通配符与LIKE运算 ...
- UNP学习 路由套接口
一.概述 在路由套接口中支持三种类型的操作: 1.进程能通过写路由套接口想内核发消息.举例:路径就是这样增加和删除的. 2.进程能在路由套接口上从内核读消息. 3.进程可以用sysctl函数得到路由表 ...
- SPI总线介绍和裸机编程分析
一.SPI总线结构 SPI(Serial Peripheral Interface)串行外设接口,是一种高速的,全双工,同步的通信总线.采用主从模式(Master Slave)架构,支持多个slave ...
- POJ 3468 A Simple Problem with Integers(线段树区间修改及查询)
Description You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. On ...