【网络流】One-Way Roads

题目描述

In the country of Via, the cities are connected by roads that can be used in both directions.

However, this has been the cause of many accidents since the lanes are not separated: The drivers frequently look at their smartphones while driving, causing them to collide with the oncoming traffic. To alleviate the problem, the politicians of Via came up with the magnificent idea to have one-way roads only, i.e., the existing roads are altered such that each can be only used in one of two possible directions. They call this “one-way-ification”.

The mayors do not want too many one-way roads to lead to their cities because this can cause traffic jam within the city: they demand that the smallest integer d be found such that there is a ‘one-way-ification’ in which for every city, the number of one-way roads leading to it is at most d.

输入

The input consists of:

• one line with an integer n (1 ≤ n ≤ 500), where n is the number of cities labeled from 1 to n;

• one line with an integer m (0 ≤ m ≤ 2.5 · 103 ), where m is the number of (bi-directional) roads;

• m lines describing the roads. Each road is described by:

– one line with two integers a and b (1 ≤ a, b ≤ n, a≠b) indicating a road between cities a and b.

There is at most one road between two cities.

输出

Output the minimum number d.

样例输入

2

1

1 2

样例输出

1

还没看出来是网络流。题目问:赋予方向,让每个点最大的入度最小。然后每条边方向信号相当于给每个点一个权值,然后一条边只能给一个点一个权值。就想到用网络流。通过满不满流来判断合法性。

方法一:二分

二分枚举每个点流向汇点的流量,如果与进来的流量相同,就说明可行,不相同则不可以。每次都要初始化并建边

#include <algorithm>
#include <iostream>
#include <cstring>
#include <string>
#include <cstdio>
#include <vector>
#include <queue>
#include <cmath>
#include <map>
#include <set>
#define ll long long
#define ull unsigned long long
const int inf=0x3f3f3f3f;
using namespace std;
const int maxn=3e3+10;
const int maxm=2e4+100;
template<class T>
void read(T &res)
{
res = 0;
char c = getchar();
T f = 1;
while(c < '0' || c > '9')
{
if(c == '-') f = -1;
c = getchar();
}
while(c >= '0' && c <= '9')
{
res = res * 10 + c - '0';
c = getchar();
}
res *= f;
}
struct Dinic
{
struct Edge
{
int next,f,to;
} e[maxm];
int head[maxn],dep[maxn],tol,ans;
int cur[maxn];
int src,sink,n;
void add(int u,int v,int f)
{
tol++;
e[tol].to=v;
e[tol].next=head[u];
e[tol].f=f;
head[u]=tol;
tol++;
e[tol].to=u;
e[tol].next=head[v];
e[tol].f=0;
head[v]=tol;
}
bool bfs()
{
queue<int>q;
memset(dep,-1,sizeof(dep));
q.push(src);
dep[src]=0;
while(!q.empty())
{
int now=q.front();
q.pop();
for(int i=head[now]; i; i=e[i].next)
{
if(dep[e[i].to]==-1&&e[i].f)
{
dep[e[i].to]=dep[now]+1;
if(e[i].to==sink)
return true;
q.push(e[i].to);
}
}
}
return false;
}
int dfs(int x,int maxx)
{
if(x==sink)
return maxx;
for(int& i=cur[x]; i; i=e[i].next)
{
if(dep[e[i].to]==dep[x]+1&&e[i].f>0)
{
int flow=dfs(e[i].to,min(maxx,e[i].f));
if(flow)
{
e[i].f-=flow;
e[i^1].f+=flow;
return flow;
}
}
}
return 0;
}
int dinic(int s,int t)
{
ans=0;
this->src=s;
this->sink=t;
while(bfs())
{
for(int i=0; i<=n; ++i)
cur[i]=head[i];
while(int d=dfs(src,inf))
ans+=d;
}
return ans;
}
void init(int n)
{
this->n=n;
memset(head,0,sizeof(head));
tol=1;
}
} G;
struct node{int u,v;}s[maxm];
int n,m;
bool check(int k){
G.init(n+m+1);
for(int i=1;i<=m;++i){
G.add(0,i,1);
G.add(i,m+s[i].u,1);
G.add(i,m+s[i].v,1);
}
for(int i=1;i<=n;++i){
G.add(m+i,n+m+1,k);
}
int max_flow=G.dinic(0,n+1+m);
if(max_flow==m){
return 1;
}
else return 0;
}
int main()
{
read(n);read(m);
G.init(n+m+1);
for(int i=1; i<=m; ++i)
{
read(s[i].u);
read(s[i].v);
}
int l=0,r=maxm+10;
int ans,mid;
while(l<r){
mid=(l+r)/2;
if(check(mid)){
ans=mid;
r=mid;
}
else l=mid+1;
}
printf("%d\n",ans);
return 0;
}

方法二:残余网络

标记流向汇点的正向边的编号。由于它点数比较少,所以可以for循环,每次让正向边流量加一然后跑残余网络,一合法就是正确答案。

#include <algorithm>
#include <iostream>
#include <cstring>
#include <string>
#include <cstdio>
#include <vector>
#include <queue>
#include <cmath>
#include <map>
#include <set>
#define ll long long
#define ull unsigned long long
const int inf=0x3f3f3f3f;
using namespace std;
const int maxn=3e3+10;
const int maxm=2e4+100;
struct Dinic
{
struct Edge
{
int next,f,to;
} e[maxm];
int head[maxn],dep[maxn],tol,ans;
int cur[maxn];
int src,sink,n;
void add(int u,int v,int f)
{
tol++;
e[tol].to=v;
e[tol].next=head[u];
e[tol].f=f;
head[u]=tol;
tol++;
e[tol].to=u;
e[tol].next=head[v];
e[tol].f=0;
head[v]=tol;
}
bool bfs()
{
queue<int>q;
memset(dep,-1,sizeof(dep));
q.push(src);
dep[src]=0;
while(!q.empty())
{
int now=q.front();
q.pop();
for(int i=head[now]; i; i=e[i].next)
{
if(dep[e[i].to]==-1&&e[i].f)
{
dep[e[i].to]=dep[now]+1;
if(e[i].to==sink)
return true;
q.push(e[i].to);
}
}
}
return false;
}
int dfs(int x,int maxx)
{
if(x==sink)
return maxx;
for(int& i=cur[x]; i; i=e[i].next)
{
if(dep[e[i].to]==dep[x]+1&&e[i].f>0)
{
int flow=dfs(e[i].to,min(maxx,e[i].f));
if(flow)
{
e[i].f-=flow;
e[i^1].f+=flow;
return flow;
}
}
}
return 0;
}
int dinic(int s,int t)
{
ans=0;
this->src=s;
this->sink=t;
while(bfs())
{
for(int i=0; i<=n; i++)
cur[i]=head[i];
while(int d=dfs(src,inf))
ans+=d;
}
return ans;
}
void init(int n)
{
this->n=n;
memset(head,0,sizeof(head));
tol=1;
}
} G;
int num[maxm];
int main()
{
int n,m,u,v;
scanf("%d%d",&n,&m);
G.init(n+m+1);
for(int i=1; i<=m; i++)
{
scanf("%d%d",&u,&v);
G.add(0,i,1);
G.add(i,m+u,1);
G.add(i,m+v,1);
}
for(int i=1; i<=n; i++)
{
G.add(m+i,n+m+1,0);
num[i]=G.tol-1;
}
int t=0;
int ans=0;
while(t<m){
ans++;
for(int i=1;i<=n;i++){
G.e[num[i]].f+=1;
}
t+=G.dinic(0,n+m+1);
}
printf("%d\n",ans);
return 0;
}

【网络流】One-Way Roads的更多相关文章

  1. 图论常用算法之一 POJ图论题集【转载】

    POJ图论分类[转] 一个很不错的图论分类,非常感谢原版的作者!!!在这里分享给大家,爱好图论的ACMer不寂寞了... (很抱歉没有找到此题集整理的原创作者,感谢知情的朋友给个原创链接) POJ:h ...

  2. HDU5889 Barricade(最短路)(网络流)

    Barricade Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total S ...

  3. HDU 5889 (最短路+网络流)

    Barricade Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total S ...

  4. HDU 3416 Marriage Match IV (最短路径,网络流,最大流)

    HDU 3416 Marriage Match IV (最短路径,网络流,最大流) Description Do not sincere non-interference. Like that sho ...

  5. SGU 206. Roads

    206. Roads time limit per test: 0.5 sec. memory limit per test: 65536 KB input: standard output: sta ...

  6. HDU 5352——MZL's City——————【二分图多重匹配、拆点||网络流||费用流】

    MZL's City Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total ...

  7. CF546E Soldier and Traveling(网络流,最大流)

    CF546E Soldier and Traveling 题目描述 In the country there are \(n\) cities and \(m\) bidirectional road ...

  8. 【题解】Paid Roads [SP3953] [Poj3411]

    [题解]Paid Roads [SP3953] [Poj3411] 传送门:\(\text{Paid}\) \(\text{Roads}\) \(\text{[SP3953]}\) \(\text{[ ...

  9. Codeforces 546 E:士兵的旅行 最大网络流

    E. Soldier and Traveling time limit per test 1 second memory limit per test 256 megabytes input stan ...

随机推荐

  1. Maven工程配置依赖

    1.下载 安装 官网下载maven :http://maven.apache.org/download.cgi ,下载时候注意版本,IDEA旧版本如我用的2017在安装Maven时可能会报错,此时别下 ...

  2. 使用H5搭建webapp主页面

    使用H5搭建webapp主页面 前言: 在一个h5和微信小程序火热的时代,作为安卓程序员也得涉略一下h5了,不然就要落后了,据说在简历上可以加分哦,如果没有html和css和js基础的朋友,可以自行先 ...

  3. CF940F Machine Learning(带修莫队)

    首先显然应该把数组离散化,然后发现是个带修莫队裸题,但是求mex比较讨厌,怎么办?其实可以这样求:记录每个数出现的次数,以及出现次数的出现次数.至于求mex,直接暴力扫最小的出现次数的出现次数为0的正 ...

  4. OpenCV2基础操作----直线、矩形、圆、椭圆函数的使用

    opencv2几个画图函数的调用 要用到几个随机变量: int fr = rand()%frame.rows; int fc = rand()%frame.cols; int b = rand()%2 ...

  5. Java 容器使用中如何选择

    Collection  ├List │├LinkedList │├ArrayList │└Vector │└Stack ├Queue │├Deque │└LinkedList └Set   ├Sort ...

  6. UML-架构分析-基础

    1.何时开始架构分析? 最好在第一次迭代前开始.因为,架构分析的失败会导致高风险.如:必须支持英语.在一秒响应时间内支持500个并发事务. UP是迭代和进化的(不是瀑布式的),所以架构分析和开发工作齐 ...

  7. ansible-playbook权限提升多种方式

    ansible-playbook 可以方便快速的批量执行部署和运维任务,对于不同的场景和服务器,需要使用不同的权限提升方式. 最佳实现:为了提高playbook的兼容性,跟功能没有直接关系的权限提升脚 ...

  8. dp--背包--开心的金明

    题目描述 金明今天很开心,家里购置的新房就要领钥匙了,新房里有一间他自己专用的很宽敞的房间.更让他高兴的是,妈妈昨天对他说:“你的房间需要购买哪些物品,怎么布置,你说了算,只要不超过N元钱就行”.今天 ...

  9. LeetCode——230. 二叉搜索树中第K小的元素

    给定一个二叉搜索树,编写一个函数 kthSmallest 来查找其中第 k 个最小的元素. 说明: 你可以假设 k 总是有效的,1 ≤ k ≤ 二叉搜索树元素个数. 示例 1: 输入: root = ...

  10. Consul集群版容器化部署与应用集成

    背景 由于公司目前的主要产品使用的注册中心是consul,consul需要用集群来保证高可用,传统的方式(Nginx/HAProxy)会有单点故障问题,为了解决该问题,我开始研究如何只依赖consul ...