One-Way Roads 网络流(最大流)

One-Way Roads

时间限制: 1 Sec  内存限制: 64 MB
提交: 234  解决: 39
[提交] [状态] [讨论版] [命题人: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 

当时并不会,借鉴大牛的博客学习了一下:https://blog.csdn.net/winter2121/article/details/82953668

题目大意:给出一个无向图,把无向边变成单向的,每个点的入度最多为d,求最小的d。

建图方式:对于每一条边我们用一个中间节点连向两个端点,容量为1。然后将中转点于原点相连,因为每个中间点只能选择一个端点,(原点到i的容量为1,所以不存在同时选择1-2 和2-1 两条边。),每个点到汇点的容量x,即这个最大的入度,需要我们去二分枚举。

我的理解:之所以这样建图是因为,m条边,有m个中转点,所以说流入的流量肯定为m,每条边可以为两个端点的其中一个分配一个入度,对于每个点到汇点的容量x需要我们二分去枚举(这个可以理解为i点的入度),然后通过看最大流是否为m(所有点的入度之和为m)来判断是否合法(之所以这样判断应该是因为,如果存在x小于某一个个点的入度,则当前的m不能够流满)。

需要注意的点:这个题EK会超时,普通的dinic也会超时,加不加当前弧优化就是超时与8ms的区别。。。

#include<iostream>
#include<cstdio>
#include<vector>
#include<queue>
#include<set>
#include<map>
#include<algorithm>
#include<cstring>
using namespace std;
#define rep(i,j,k) for(int i=j;i<=k;i++)
#define sca(x) scanf("%d",&x)
#define per(i,j,k) for(int i=j;i>=k;i--)
#define inf 0x3f3f3f3f
#define LL long long
#define N 20005
#define inf 0x3f3f3f3f

int S,T;
struct edg
{
    int to,w,nt;
}g[N*2];
int tot=0;
int head[N];
void addedg(int u,int v,int w)
{
    g[tot].to=v;
    g[tot].w=w;
    g[tot].nt=head[u];
    head[u]=tot++;

    g[tot].to=u;
    g[tot].w=0;
    g[tot].nt=head[v];
    head[v]=tot++;

}

int dep[N],cur[N];
bool bfs(int s,int t)
{
    memset(dep,-1,sizeof(dep));
    queue<int>q;
    q.push(s);
    dep[s]=0;
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        for(int i=head[u];i!=-1;i=g[i].nt)
        {
            int to=g[i].to;
            if(dep[to]==-1&&g[i].w>0)
            {
                dep[to]=dep[u]+1;
                q.push(to);
            }
        }
    }
    return dep[t]!=-1;
}

int dfs(int now,int flow)
{
    int tmp;
    if(now==T) return flow;
    for(int& i=cur[now];i!=-1;i=g[i].nt)
    {
        int to=g[i].to;
        if(dep[to]==dep[now]+1&&g[i].w>0&&
         (tmp=dfs(to,min(flow,g[i].w))))
        {
            g[i].w-=tmp;
            g[i^1].w+=tmp;
            return tmp;
        }
    }
    return 0;
}
int dinic(int s,int t,int n)
{
    int ans=0;
    int d;
    while(bfs(s,t)){
        rep(i,0,n)cur[i]=head[i];
        while(d=dfs(s,inf))
            ans+=d;
    }
    return ans;
}
int main()
{
     int n,m;
     scanf("%d%d",&n,&m);
     S=0;
     int tmp=n+1;
     memset(head,-1,sizeof(head));
     rep(i,1,m)
     {
         int x,y;
         scanf("%d%d",&x,&y);
         addedg(tmp,x,1);
         addedg(tmp,y,1);
         tmp++;
     }
     T=n+m+1;
     rep(i,n+1,tmp-1)addedg(0,i,1);
     int now=tot;
     rep(i,1,n)addedg(i,T,1);
     int l=0,r=m;
     while(l<r)
     {
         int mid=(l+r)>>1;
         for(int i=0;i<now;i++)g[i].w=!(i&1);
         for(int i=now;i<tot;i++)g[i].w=(i%2==0?mid:0);
         if(dinic(S,T,T)==m)r=mid;
         else l=mid+1;
     }
     printf("%d\n",r);
}

猜你喜欢

转载自blog.csdn.net/weixin_40894017/article/details/83066320