Reverse a Road II
Time Limit: 10000ms, Special Time Limit:25000ms, Memory Limit:65536KB
Total submit users: 10, Accepted users: 6
Problem 13411 : No special judgement
Problem description

JAG Kingdom is a strange kingdom such that its N cities are connected only by one-way roads. The N cities are numbered 1 through N. ICPC (International Characteristic Product Corporation) transports its products from the factory at the city S to the storehouse
at the city T in JAG Kingdom every day. For efficiency, ICPC uses multiple trucks at once. Each truck starts from S and reaches T on the one-way road network, passing through some cities (or directly). In order to reduce risks of traffic jams and accidents,
no pair of trucks takes the same road.



Now, ICPC wants to improve the efficiency of daily transports, while ICPC operates daily transports by as many trucks as possible under the above constraint. JAG Kingdom, whose finances are massively affected by ICPC, considers to change the direction of one-way
roads in order to increase the number of trucks for daily transports of ICPC. Because reversal of many roads causes confusion, JAG Kingdom decides to reverse at most a single road.



If there is no road such that reversal of the road can improve the transport efficiency, JAG Kingdom need not reverse any roads. Check whether reversal of a single road can improve the current maximum number of trucks for daily transports. And if so, calculate
the maximum number of trucks which take disjoint sets of roads when a one-way road can be reversed, and the number of roads which can be chosen as the road to be reversed to realize the maximum.

Input

The input consists of multiple datasets. The number of dataset is no more than 100.



Each dataset is formatted as follows.



 

The following M lines describe the information of the roads. The i-th line of them contains two integers aiand bi(1 ≤ ai,bi≤ N, ai≠ bi), meaning that the i-th road is directed from ai to bi.



The end of input is indicated by a line containing four zeros.

Output

For each dataset, output two integers separated by a single space in a line as follows: If reversal of a single road improves the current maximum number of trucks for daily transports, the first output integer is the new maximum after reversal of a road,
and the second output integer is the number of roads which can be chosen as the road to be reversed to realize the new maximum. Otherwise, i.e. if the current maximum cannot be increased by any reversal of a road, the first output integer is the current maximum
and the second output integer is 0.

Sample Input
4 4 1 4
1 2
3 1
4 2
3 4
7 8 1 7
1 2
1 3
2 4
3 4
4 5
4 6
5 7
7 6
6 4 5 2
1 2
1 3
4 5
5 6
10 21 9 10
9 1
9 2
9 3
9 4
10 1
10 2
10 3
10 4
1 5
2 5
2 6
3 6
3 7
4 7
4 8
1 8
5 10
6 10
7 10
10 8
10 9
2 15 1 2
1 2
1 2
1 2
1 2
1 2
1 2
1 2
1 2
1 2
1 2
1 2
1 2
1 2
1 2
1 2
0 0 0 0
Sample Output
1 2
2 1
0 0
4 6
15 0
Problem Source

JAG Practice Contest for ACM-ICPC Asia Regional 2014

题意:给一个有向图,n个点,m条边,起点S ,终点T。现有非常多个机器人要从S走到T,每条边仅仅能走一个机器人,现要能够改一条边的方向,问最多有多少个机器人能够从S走到T。而且有多少种改法。(假设没有改变边的方向,则改法为0。)

解题:如要没有加条件:能够改一条边。那么这题就是找最多有多少条路要以从起点S走到T。建图:每条有向边的边权为1,用最大流跑一次。那么如今要改一条边的方向:假设要更改的边是走过的边,那么不会使走法添加,有能够还使路的条数降低,所以改的边一定不是满流的边(即走过的边)。如今要改变一条不在走过的边< u  ,  v >变成<v , u>,使得能够增流,那么仅仅要从S沿着没有走过的边到  v 。再从u沿着没有走过的边 到 T。这样就能够使得路的条数增多。

那么这样我们就能够用BFS标记 SF[] 能从S点沿着最大流每条边的残流量>0的边走到的一些点V,再标记
TF[] 能从T点沿着最大流每条边的残流量==0的边走到一些点U(即表示:能从U沿着那些边走到T)。最后仅仅要枚举原来不在走过的边<u , v >,假设:SF[v]==1&&TF[u]==1则改变此边方向能够增流。方案数k+1。

最后的最多机器人数ans = maxflow + k>0 ? 1 : 0  。

#include<stdio.h>
#include<string.h>
#include<queue>
#include<algorithm>
using namespace std;
#define captype int const int MAXN = 1010; //点的总数
const int MAXM = 40010; //边的总数
const int INF = 1<<30;
struct EDG{
int to,next;
captype cap;
} edg[MAXM];
int eid,head[MAXN];
int gap[MAXN]; //每种距离(或可觉得是高度)点的个数
int dis[MAXN]; //每一个点到终点eNode 的最短距离
int cur[MAXN]; //cur[u] 表示从u点出发可流经 cur[u] 号边
int pre[MAXN]; void init(){
eid=0;
memset(head,-1,sizeof(head));
}
//有向边 三个參数。无向边4个參数
void addEdg(int u,int v,captype c,captype rc=0){
edg[eid].to=v; edg[eid].next=head[u];
edg[eid].cap=c; head[u]=eid++; edg[eid].to=u; edg[eid].next=head[v];
edg[eid].cap=rc; head[v]=eid++;
}
captype maxFlow_sap(int sNode,int eNode, int n){//n是包含源点和汇点的总点个数,这个一定要注意 memset(gap,0,sizeof(gap));
memset(dis,0,sizeof(dis));
memcpy(cur,head,sizeof(head));
pre[sNode] = -1;
gap[0]=n;
captype ans=0; //最大流
int u=sNode;
while(dis[sNode]<n){ //推断从sNode点有没有流向下一个相邻的点
if(u==eNode){ //找到一条可增流的路 for(int i=pre[u]; i!=-1; i=pre[edg[i^1].to]){
edg[i].cap-=1;
edg[i^1].cap+=1; //可回流的边的流量
}
ans+=1;
u=sNode;
continue;
}
bool flag = false; //推断是否能从u点出发可往相邻点流
int v;
for(int i=cur[u]; i!=-1; i=edg[i].next){
v=edg[i].to;
if(edg[i].cap>0 && dis[u]==dis[v]+1){
flag=true;
cur[u]=pre[v]=i;
break;
}
}
if(flag){
u=v;
continue;
}
//假设上面没有找到一个可流的相邻点。则改变出发点u的距离(也可觉得是高度)为相邻可流点的最小距离+1
int Mind= n;
for(int i=head[u]; i!=-1; i=edg[i].next)
if(edg[i].cap>0 && Mind>dis[edg[i].to]){
Mind=dis[edg[i].to];
cur[u]=i;
}
gap[dis[u]]--;
if(gap[dis[u]]==0) return ans; //当dis[u]这样的距离的点没有了,也就不可能从源点出发找到一条增广流路径
//由于汇点到当前点的距离仅仅有一种,那么从源点到汇点必定经过当前点。然而当前点又没能找到可流向的点,那么必定断流
dis[u]=Mind+1;//假设找到一个可流的相邻点。则距离为相邻点距离+1,假设找不到,则为n+1
gap[dis[u]]++;
if(u!=sNode) u=edg[pre[u]^1].to; //退一条边
}
return ans;
}
bool flag[MAXM] , SF[MAXN] , TF[MAXN];
void bfs(int s ,bool flag)
{
queue<int>q;
int u , v;
q.push(s );
while(!q.empty())
{
u = q.front(); q.pop();
for(int i=head[u]; ~i ; i=edg[i].next)
{
v=edg[i].to;
if(flag)
{
if(SF[v]||!edg[i].cap)continue;
SF[v]=1;
q.push(v);
}
else{
if(TF[v]||!edg[i^1].cap)continue;
TF[v]=1;
q.push(v);
}
}
}
}
inline void scanf(int& num )
{
char ch;
while(ch=getchar())
{
if(ch>='0'&&ch<='9')break;
}
num = ch-'0';
while(ch=getchar())
{
if(ch<'0'||ch>'9')break;
num = num*10+ch-'0';
}
}
int main()
{
int n,m,vs , vt , u ,v; while(scanf("%d%d%d%d",&n,&m,&vs,&vt)>0&&n+m+vs+vt!=0)
{
init();
for(int i=0; i<m; i++)
{
scanf(u);
scanf(v);
addEdg(u , v ,1);
}
memset(flag , 0 , (m+3)*sizeof(bool));
memset(SF,0,sizeof(SF));
memset(TF,0,sizeof(TF));
int ans , k=0 ;
ans = maxFlow_sap(vs , vt , n );
for(int i=0; i<m; i++)
if(edg[i<<1].cap==0)
flag[i]=1;
SF[vs ] =1; bfs(vs , 1);
TF[vt] = 1; bfs(vt , 0); for(int i=0; i<m; i++)
if(!flag[i]){
v=edg[i<<1|1].to;
u=edg[i<<1].to; if(SF[u]&&TF[v])
k++;
}
if(k) ans++;
printf("%d %d\n",ans , k);
}
}

HNU 13411 Reverse a Road II(最大流+BFS)经典的更多相关文章

  1. 【leetcode】Reverse Linked List II

    Reverse Linked List II Reverse a linked list from position m to n. Do it in-place and in one-pass. F ...

  2. 14. Reverse Linked List II

    Reverse Linked List II Reverse a linked list from position m to n. Do it in-place and in one-pass. F ...

  3. 【原创】Leetcode -- Reverse Linked List II -- 代码随笔(备忘)

    题目:Reverse Linked List II 题意:Reverse a linked list from position m to n. Do it in-place and in one-p ...

  4. 92. Reverse Linked List II

    题目: Reverse a linked list from position m to n. Do it in-place and in one-pass. For example:Given 1- ...

  5. lc面试准备:Reverse Linked List II

    1 题目 Reverse a linked list from position m to n. Do it in-place and in one-pass. For example:Given 1 ...

  6. 【LeetCode练习题】Reverse Linked List II

    Reverse Linked List II Reverse a linked list from position m to n. Do it in-place and in one-pass. F ...

  7. [Linked List]Reverse Linked List,Reverse Linked List II

    一.Reverse Linked List  (M) Reverse Linked List II (M) Binary Tree Upside Down (E) Palindrome Linked ...

  8. LeetCode之“链表”:Reverse Linked List && Reverse Linked List II

    1. Reverse Linked List 题目链接 题目要求: Reverse a singly linked list. Hint: A linked list can be reversed ...

  9. 4990: [Usaco2017 Feb]Why Did the Cow Cross the Road II 线段树维护dp

    题目 4990: [Usaco2017 Feb]Why Did the Cow Cross the Road II 链接 http://www.lydsy.com/JudgeOnline/proble ...

随机推荐

  1. HAVING 语句

     有的时候需要对部分分组进行过滤,比如只检索人数多余1个的年龄段,有的开发人员会使用下面的SQL语句: SELECT FAge,COUNT(*) AS CountOfThisAge FROM T_Em ...

  2. luogu P1095 守望者的逃离

    题目描述 恶魔猎手尤迪安野心勃勃,他背叛了暗夜精灵,率领深藏在海底的娜迦族企图叛变.守望者在与尤迪安的交锋中遭遇了围杀,被困在一个荒芜的大岛上.为了杀死守望者,尤迪安开始对这个荒岛施咒,这座岛很快就会 ...

  3. [CF678F]Lena and Queries

    题意: 初始有一个空集合$n$个操作有三种操作,如下:$1\ a\ b$表示向集合中插入二元组$(a,b)$$2\ i$表示删除第$i$次操作时所插入的二元组$3\ q$表示询问当前集合的二元组中,$ ...

  4. 【set】【multiset】bzoj1058 [ZJOI2007]报表统计

    对n个位置,每个位置维护一个vector. 每次插入,可能对MIN_SORT_GAP产生的影响,只可能是 插入元素 和 它的 前驱 后继 造成的,用一个set维护(存储所有序列中的元素). 我们还得维 ...

  5. python3 开发面试题(%s和format的区别)5.31

    在格式化字符串中有两种方法: 1.%s 2.format 大家常用的是哪一种方法?为什么要用你选的这种方法? 我们先看一个例子: 首先我们定义一个我军需要击杀的恐怖分子的地理坐标为 c=(128,12 ...

  6. Exercise01_11

    public class Population{ public static void main(String[] args){ int sum,s; s=365*5*24*60*60; sum=31 ...

  7. [功能]点击ImageView进入页面,时间响应者链实现

    app点击一个按钮跳转到另外一个控制器非常常用,但是如果是点击的是UIImageView如何通过模态视图进入另外一个控制器呢?万一这个UIImageView在自定义的cell或者view里面,那该如何 ...

  8. 【Echarts】百度Echarts的使用入门+两个简单的小例子+心得

    Echarts对于展示结果,有一个很好的表达方式. 1.首先,在官网将js下载到本地,引用到页面上 这里是在开发环境,所以下载最后源代码这个 managerResult.jsp <%@ page ...

  9. MySql中的concat()相关函数

    concat 函数的基本应用一: SQL CONCAT函数用于将两个字符串连接起来,形成一个单一的字符串.试试下面的例子: SQL> SELECT CONCAT('FIRST ', 'SECON ...

  10. python socket timeout设置

    需要在调用socket的connect方法之前设置settimeout(time)方法,另外在设置之后要将再次调用settimeout(None)来设置socket进入阻塞模式. 如下代码示例: so ...