【网络流】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 ...
随机推荐
- C++中获取当前时间并格式化输出
#include <string> #include <time.h> using namespace std; string getTime() { time_t timep ...
- Windows10 与 WSL(Ubuntu)的文件互访
从WSL访问win10的文件 > cd /mnt 从win10访问WSL的文件 打开Ubuntu > explorer.exe . (后面的点不要漏掉)
- Ubuntu 不插优盘无法启动
ubuntu安装成功后只能通过优盘启动 不插优盘就无法启动 启动后拔掉优盘没问题 难道动过优盘安装的 2013-06-16 20:01 提问者悬赏:5分 | 理电池 | 分类:电脑外接设备 | 浏览2 ...
- VS程序不显示控制台
之所以会有这样的想法是因为,有时候我会用到一些库,这些库在使用的时候会在控制台输出一些信息,虽然这是无可厚非的事情,但是,如果我写了一个界面,这个时候当然是希望要显示什么就显示在界面上,或者就不要显示 ...
- 用户体验评价——win10自带微软拼音输入法
目前正在使用的一款输入法就是win10自带的微软拼音输入法, 用户界面,一直在用个人感觉最大的特点就是十分简洁,界面的布局十分清晰,可以隐藏悬浮窗让他显示在菜单栏, 另外其记住用户输入习惯方面也十分优 ...
- WOJ 1543 Array
还是聪哥给我讲的思路才知道的,起初我利用两两互质去求发现有问题,互质只是必要条件而非充分条件,后来还是用的标准思路 即其实最终只要保留最大的素数的幂即可,其他包含该素数幂但指数低的都不用了,这样就能保 ...
- kaggle——TMDB 电影票房收入预测
介绍 看电影是目前人们休闲娱乐,消遣时光的选择之一.我们都知道,有些电影的票房很高,有的电影票房却很低,那么决定票房的因素是什么呢?本次将介绍,如何根据电影上映前的一些信息来预测出该电影的票房. 知识 ...
- 直击JDD | 京东技术全景图首次展示 四大重磅智能技术驱动产业未来!
11月19日,主题为"突破与裂变"的2019京东全球科技探索者大会(JDDiscovery)在京盛大开幕,京东集团展示了完整的技术布局与先进而丰富的对外技术服务,对外明确诠释了&q ...
- C/C++源程序到可执行程序的过程
源程序.cpp 预处理得到 预处理文件.i 编译得到 汇编文件.S 汇编得到 目标文件.o 链接得到 可执行文件 例子:main.cpp fun.cpp fun.h #inclu ...
- 寒假day15
今天完成了毕设的人才动态模块,同时刷了计算机网络的相关面试题