【网络流】One-Way Roads
【网络流】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的更多相关文章
- 图论常用算法之一 POJ图论题集【转载】
POJ图论分类[转] 一个很不错的图论分类,非常感谢原版的作者!!!在这里分享给大家,爱好图论的ACMer不寂寞了... (很抱歉没有找到此题集整理的原创作者,感谢知情的朋友给个原创链接) POJ:h ...
- HDU5889 Barricade(最短路)(网络流)
Barricade Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total S ...
- HDU 5889 (最短路+网络流)
Barricade Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total S ...
- HDU 3416 Marriage Match IV (最短路径,网络流,最大流)
HDU 3416 Marriage Match IV (最短路径,网络流,最大流) Description Do not sincere non-interference. Like that sho ...
- SGU 206. Roads
206. Roads time limit per test: 0.5 sec. memory limit per test: 65536 KB input: standard output: sta ...
- HDU 5352——MZL's City——————【二分图多重匹配、拆点||网络流||费用流】
MZL's City Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total ...
- CF546E Soldier and Traveling(网络流,最大流)
CF546E Soldier and Traveling 题目描述 In the country there are \(n\) cities and \(m\) bidirectional road ...
- 【题解】Paid Roads [SP3953] [Poj3411]
[题解]Paid Roads [SP3953] [Poj3411] 传送门:\(\text{Paid}\) \(\text{Roads}\) \(\text{[SP3953]}\) \(\text{[ ...
- Codeforces 546 E:士兵的旅行 最大网络流
E. Soldier and Traveling time limit per test 1 second memory limit per test 256 megabytes input stan ...
随机推荐
- bugku-Web这是一个神奇的登陆框(sqlmap+bp)
根据url提示是让sql注入,但万能密码又无效,这里我们用sqlmap+bp来解题. 首先输入用户密码来登录用bp抓包: 如图将其保存到txt文件中,然后用SQLmap来注入 输入命令暴库:sqlma ...
- 关于构造函数中的this()和super()
今天看到一个这段代码 public DataSourcePool(String driver, String url, String user, String pwd) throws Exceptio ...
- python3+Opencv 搭建环境和基本操作
一.必备前提: Python3.5及以上版本.pip.windows环境 二.搭建opencv 该部分可以创建隔绝的Python环境来引入,参照virtualenv的使用 在目标的cmd窗口,依次输入 ...
- Java四类八种
四类: 整数类型,浮点类型,字符型,布尔型 八种: byte,short,int,long,float,double,char,boolean
- Django项目同步到码云
本篇博客主要记录下将刚刚初始化后的Django项目部署到码云中,首先我们需要到码云中注册一个账号,下面会讲解下如何在码云中建立一个仓库,再将其克隆到本地.最后将本地的项目推送到码云的仓库中. 码云内初 ...
- 删除xcode项目中不再使用的图片资源
1. 利用工具 下载地址 http://jeffhodnett.github.io/Unused/ 运行效果如下 2. 通过终端 执行 shell 命令 a. 第一步建立.sh 文件 如 ...
- LeetCode——79. 单词搜索
给定一个二维网格和一个单词,找出该单词是否存在于网格中. 单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中"相邻"单元格是那些水平相邻或垂直相邻的单元格.同一个单元格内的字 ...
- VNC viewer 无法打开oracle 11g图形界面方案
VNC viewer 无法打开oracle 11g图形界面方案 1.检查交换空间失败 检查交换空间:可用的交换空间为35MB,所需的交换空间为150MB.未通过 创建swapfile: root权限下 ...
- 双向链表的双向冒泡排序 c++
#include<iostream> using namespace std; #define swap(a,b) {int t;t = a;a = b;b = t;} //节点类型的定义 ...
- ssh 账号密码登录设置
找到/etc/ssh/sshd_config文件中的 PasswordAuthentication no 改为PasswordAuthentication yes 并保存. 重启ssh服务:sudo ...