2785: One-Way Roads

时间限制: 1 Sec  内存限制: 64 MB
提交: 196  解决: 31
[提交] [状态] [讨论版] [命题人:admin]

题目描述

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

来源/分类

GCPC2016 

[提交] [状态]

【题意】

给出无向图,对于每一条边,现在把它变成有向。完成后,每个点的入度为d,最大的入度为maxd,求最小的maxd

【分析】

网络流建模。

建立超级源点S汇点T,在原图中每一条有向边的中间插入一个附加点j,源点S向所有的j连一条边,容量为1,然后j向其两边的那两个点分别连边,容量为1,这样就满足了,附加点j仅能选择一条出路。最后将所有点向T连一条边,容量为x(未知)。

二分求x。每次二分都要将图恢复成跑最大流之前的图。试一下当前枚举的x能否使得模型图的最大流达到m,达到才是满足的x

【代码】

#include<bits/stdc++.h>
#define read(i) scanf("%d",&i)
using namespace std;
typedef long long ll;
const int MAX=1e5+5;
struct node{
    int t,next;
    int flow;
}edge[MAX<<1];
int head[MAX],cur[MAX],cnt;
void initedge(int n)
{
    memset(head,-1,sizeof(head[0])*++n);cnt=0;
}
void addedge(int u,int v,int cap)
{
    edge[cnt]=node{v,head[u],cap};
    head[u]=cnt++;
    edge[cnt]=node{u,head[v],0};
    head[v]=cnt++;
}

int deep[MAX],temp[MAX];
bool bfs(int s,int t,int ver)
{
    for(int i=0;i<=ver;i++)deep[i]=-1;
    deep[s]=1;
    int front=0,tail=0,*q=temp;
    q[tail++]=s;
    while(front<tail)
    {
        int u=q[front++];
        for(int i=head[u];~i;i=edge[i].next)
        {
            int v=edge[i].t;
            if(deep[v]==-1&&edge[i].flow>0)
            {
                deep[v]=deep[u]+1;
                q[tail++]=v;
            }
        }
    }
    return deep[t]>0;
}
int dfs(int s,int t,int minflow)
{
    if(s==t)return minflow;
    int flow=0;
    for(int &i=cur[s];~i;i=edge[i].next)
    {
        int v=edge[i].t;
        if(deep[s]+1!=deep[v]||edge[i].flow<=0)continue;
        ll temp=dfs(v,t,min(minflow,edge[i].flow));
        edge[i].flow-=temp;
        edge[i^1].flow+=temp;
        flow+=temp;
        if(flow==minflow)return flow;
    }
    if(flow==0)deep[s]=-1;
    return flow;
}
int dinic(int s,int t,int ver)
{
    int flow=0;
    while(bfs(s,t,ver))
    {
        for(int i=0;i<=ver;i++)cur[i]=head[i];
        flow+=dfs(s,t,1e9);
    }
    return flow;
}

int main()
{
    int n,m,u,v;
    read(n); read(m);
    initedge(n);
    for(int i=1;i<=m;i++)
    {
        read(u); read(v);
        addedge(0,i,1);
        addedge(i,u+m,1);
        addedge(i,v+m,1);
    }
    int tag=cnt;
    for(int i=1;i<=n;i++)addedge(i+m,n+m+1,1e9);
    int l=0,r=m,mid;
    while(l<r)
    {
        mid=(l+r)>>1;
        for(int i=0;i<tag;i++)edge[i].flow=(i&1)?0:1;
        for(int i=tag;i<cnt;i++)edge[i].flow=(i&1)?0:mid;

        if(dinic(0,n+m+1,n+m+1)==m)r=mid;
        else l=mid+1;
    }
    printf("%d\n",r);
}

 

10-06 20:46