zoukankan      html  css  js  c++  java
  • 【网络流】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
    ",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
    ",ans);
        return 0;
    }
    
    
    不要忘记努力,不要辜负自己 欢迎指正 QQ:1468580561
  • 相关阅读:
    嵌入式开发之davinci--- spi 中的时钟极性CPOL和相位CPHA
    Setting up a Single Node Cluster Hadoop on Ubuntu/Debian
    Install Java JDK JRE on Ubuntu/Debian with Apt-Get
    使用WICleanup清理Windows Installer 冗余文件
    WinSxS文件夹瘦身
    Linux时间同步+国内常用的NTP服务器地址
    How to fix Mysql table crashes
    Monitorix:一款面向Linux的轻型系统和网络监测工具
    How To Secure Apache with Let's Encrypt on Ubuntu (Free SSL)
    Latex表格太宽处理方法 (How to shorten Latex table length)
  • 原文地址:https://www.cnblogs.com/smallocean/p/9749078.html
Copyright © 2011-2022 走看看