【网络流】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 ...
随机推荐
- Linux笔记01
linux目录结构 : linux只有一个目录. usr:等价于programfiles: etc:存放系统配置 root:管理员(超级用户)目录, home:存放其他用户的目录: lib:共享包: ...
- PAT 2018 秋
A 1148 Werewolf - Simple Version 思路比较直接:模拟就行.因为需要序列号最小的两个狼人,所以以狼人为因变量进行模拟. #include <cstdio> # ...
- [极客大挑战 2019]Upload
0x00 知识点 一个常规上传题目,知识点全都来自前几天写的文章: https://www.cnblogs.com/wangtanzhi/p/12243206.html 1:某些情况下绕过后缀名检测: ...
- aliyun服务器lamp配置
1.安装Apache:yum install httpd 2.安装php: yum install php 3.安装mysql客户端:yum install mysql 4.安装mysql服务端:yu ...
- Vue-router(4)之路由跳转
路由传参 案例:现在需要展示一个电影列表页,点击每一部电影,会跳转到该部电影详情页(跳转时携带type和id) 代码实现(未携带type): index.js import Vue from 'vue ...
- 吴裕雄--天生自然MySQL学习笔记:MySQL 函数
ASCII(s) 返回字符串 s 的第一个字符的 ASCII 码. SELECT ASCII(CustomerName) AS NumCodeOfFirstChar FROM Customers; C ...
- 吴裕雄--天生自然 JAVASCRIPT开发学习:计时事件
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...
- P3370 【模板】字符串哈希 题解
地址:https://www.luogu.org/problem/P3370 求不同字符串的数量 这题用set也可以过,但是hash更高大上嘛. 哈希其实就是将一个字符串映射成一个值,并且要让这些值不 ...
- 2019年春PAT甲级考试
这次考试不是很理想,一道题目没能做完. 自己原因差不多三条: 1.自己实力不够,准备时间也有点仓促,自己没能做到每道题目都有清晰的思路. 2.考试的心理素质不行,因为设备原因东奔西跑浪费了挺多时间,自 ...
- mybatis连接mysql(jdbc)常见问题
问题1:java.io.IOException: Could not find resource com/xxx/xxxMapper.xml IDEA是不会编译src的java目录的xml文件,所以在 ...