[网络流24题#11] 航空路线 [网络流,最大权值最大流]

只需要把费用流的Spfa中的小于号改一下就好了,对于题目中要求要飞过去在飞回来,只需要一律把边的方向定为从顶点编号较小的向顶点编号较大的,把顶点1和n的边的容量定为2,其余边为1即可。

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <ctime>
#include <map>
#include <string>
#include <queue>

using namespace std;

template<const int _n,const int _m>
struct Edge
{
    struct Edge_base { int    to,next,w,c; }e[_m];
    int    cnt,p[_n];
    Edge() { clear(); }
    int    start(const int x) { return p[x]; }
    void    insert(const int x,const int y,const int z,const int zz)
    { e[++cnt].to=y; e[cnt].next=p[x]; e[cnt].w=z; e[cnt].c=zz; p[x]=cnt; return ; }
    void    clear() { cnt=1,memset(p,0,sizeof(p)); }
    Edge_base&    operator[](const int x) { return e[x]; }
};

Edge<310,210000>    e;
map<string,int>        Map;
int    n,m,Cost,SSS,TTT;
int    Dis[310],cur[310];
bool    visited[310];

bool    Spfa(const int S)
{
    int    i,t,temp;
    queue<int>    Q;
    memset(Dis,0x80,sizeof(Dis));
    memset(visited,0,sizeof(visited));
    Dis[S]=0;
    visited[S]=true;
    Q.push(S);
    while(!Q.empty())
    {
        t=Q.front(),Q.pop();visited[t]=false;
        for(i=e.start(t);i;i=e[i].next)
        {
            temp=e[i].to;
            if(Dis[temp]<Dis[t]+e[i].c && e[i].w)
            {
                Dis[temp]=Dis[t]+e[i].c;
                if(!visited[temp])
                {
                    Q.push(temp);
                    visited[temp]=true;
                }
            }
        }
    }
    return Dis[TTT]!=(int)0x80808080;
}

int    Dfs(const int S,const int bk)
{
    if(S==TTT)return bk;
    int    rest=bk;
    visited[S]=true;
    for(int &i=cur[S];i;i=e[i].next)
    {
        if(Dis[S]+e[i].c==Dis[e[i].to] && e[i].w && !visited[e[i].to])
        {
            int    flow=Dfs(e[i].to,min(rest,e[i].w));
            Cost+=flow*e[i].c;
            e[i].w-=flow;
            e[i^1].w+=flow;
            if((rest-=flow)<=0)break;
        }
    }
    visited[S]=false;
    if(bk==rest)Dis[S]=0x3f3f3f3f;
    return bk-rest;
}

int    Dinic()
{
    int    flow=0;
    while(Spfa(SSS))
    {
        memcpy(cur,e.p,sizeof(cur));
        flow+=Dfs(SSS,0x3f3f3f3f);
    }
    return Cost;
}

int main()
{
    freopen("in","r",stdin);
    freopen("out","w",stdout);
    int    i;
    string    str,str1,str2;

    cin >> n >> m;
    SSS=n<<1|1,TTT=SSS+1;
    for(i=1;i<=n;++i)
    {
        cin >> str;
        Map[str]=i;
        e.insert(i+n,i,1,0);
        e.insert(i,i+n,0,0);
    }

    e.insert(SSS,1,2,0);
    e.insert(1,SSS,0,0);
    e.insert(n+n,TTT,2,0);
    e.insert(TTT,n+n,0,0);

    for(i=1;i<=m;++i)
    {
        cin >> str1 >> str2;
        int x=Map[str1],y=Map[str2];
        if(x>y)swap(x,y);
        e.insert(x,y+n,x!=1?x!=n?1:2:2,1);
        e.insert(y+n,x,0,-1);
    }

    int    temp=Dinic();
    if(temp)cout << temp << endl;
    else    cout << "No Solution!" << endl;

    return 0;
}
时间: 2024-10-26 15:08:00

[网络流24题#11] 航空路线 [网络流,最大权值最大流]的相关文章

【网络流24题】航空线路问题(费用流)

[网络流24题]航空线路问题(费用流) 题面 Cogs数据有误,提供洛谷题面 题解 这题和原来做过的一道题周游加拿大是一模一样的 所以,这题DP+记录方案应该也是可行的 来考虑网络流的做法 现在的来回,被看成是去两次 所以流量被限定死了,为2 因此要考虑费用流来求解. 每个点只能经过一次 很显然先拆点 如果一个城市被访问了 那么,他的两个点直接的流量是一定存在的 为了记录下这个点被访问过 所以,给定它一个费用1 然后其他的连边和原来做的题目没有什么区别 对于每一条航线,从\(i'\)向\(j\)

【网络流24题】餐巾计划问题(最小费用最大流)

[网络流24题]餐巾计划问题(最小费用最大流) 题面 COGS 洛谷上的数据范围更大,而且要开longlong 题解 餐巾的来源分为两种: ①新买的 ②旧的拿去洗 所以,两种情况分别建图 先考虑第一种 因为新买餐巾没有任何限制,并且随时可以买 所以直接从源点向每一天连边,容量为INF,费用为餐巾的价格 因为流要流出去,所以每个点向汇点连边,容量为每天的用量,费用为0 第二种,旧的拿去洗 首先考虑一下怎么算有多少旧的餐巾 每天用旧的餐巾的数量值一定的,不可能变多 因此从源点向这些点连边,容量为每天

【网络流24题】最长不下降子序列(最大流,动态规划)

[网络流24题]最长不下降子序列(最大流,动态规划) 题面 Cogs 题解 很有趣的一道题目 尽管我自己还是有一些懵逼 第一问,直接大力DP一下,不解释了 第二问,考虑到一个长度为ans的子序列的开头 他的dp值一定等于ans, 所以,如果一个点的dp值为ans,就从源点连过去,容量为1 因为每个数只能用一次,因此拆点 自己向自己的新点连容量为1的边 一个子序列的结束的位置其dp值必定为1 所以从dp值为1的新点向汇点连边,容量为1 接下来考虑点与点之间的关系 如果dp[i]=dp[j]+1 并

LibreOJ #6001. 「网络流 24 题」太空飞行计划 最大权闭合图

#6001. 「网络流 24 题」太空飞行计划 内存限制:256 MiB时间限制:1000 ms标准输入输出 题目类型:传统评测方式:Special Judge 上传者: 匿名 提交提交记录统计讨论测试数据 题目描述 W 教授正在为国家航天中心计划一系列的太空飞行.每次太空飞行可进行一系列商业性实验而获取利润.现已确定了一个可供选择的实验集合 E={E1,E2,?,Em} E = \{ E_1, E_2, \cdots, E_m \}E={E?1??,E?2??,?,E?m??},和进行这些实验

LiberOJ 6004. 「网络流 24 题」圆桌聚餐 网络流版子题

#6004. 「网络流 24 题」圆桌聚餐 内存限制:256 MiB时间限制:5000 ms标准输入输出 题目类型:传统评测方式:Special Judge 上传者: 匿名 提交提交记录统计讨论测试数据 题目描述 假设有来自 n nn 个不同单位的代表参加一次国际会议.每个单位的代表数分别为 ri r_ir?i??.会议餐厅共有 m mm 张餐桌,每张餐桌可容纳 ci c_ic?i?? 个代表就餐.为了使代表们充分交流,希望从同一个单位来的代表不在同一个餐桌就餐. 试设计一个算法,给出满足要求的

网络流24题11

https://loj.ac/problem/6122 来回相当于同时在起点开始不相交 跑一个最大费用最大流 最后输出答案时沿着反向边有容量dfs就行了 #include <iostream> #include <map> #include <cstring> #include <queue> using namespace std; map<string,int> mapp; const int maxn = 110; string str[m

【网络流24题】No.19 负载平衡问题 (费用流)

[题意] G 公司有 n 个沿铁路运输线环形排列的仓库, 每个仓库存储的货物数量不等. 如何用最少搬运量可以使 n 个仓库的库存数量相同.搬运货物时,只能在相邻的仓库之间搬运. 输入文件示例input.txt517 9 14 16 4 输出文件示例output.txt11 [分析] 其实我觉得这题可以贪心啊..n^2贪心??.没细想.. 打的是费用流.. 大概这样建图: 懒得写了..凌乱之美.. 求满流费用.. 1 #include<cstdio> 2 #include<cstdlib&

[cogs729] [网络流24题#5] 圆桌聚餐 [网络流,最大流,多重二分图匹配]

建图:从源点向单位连边,边权为单位人数,从单位向圆桌连边,边权为1,从圆桌向汇点连边,边权为圆桌容量. #include <iostream> #include <algorithm> #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <ctime> #include <queue> #includ

[网络流24题] 软件补丁问题

题目链接:戳我 感觉虽然在所谓的网络流24题编制里,但是并没有看出来怎么用网络流做?(听说网络流24题全名不叫网络流24题???) 看到n的范围挺小的,我们考虑状压. 转移的过程可以放到图论里面,因为要求费用最小,所以我们想到了最短路!(笑 所以就是dij+状压转移嘛qwqwq(我就是不写spfa!!!) 注意一下非法情况的判断为f1里面包含,但是当前情况u不包含.或者f2里面不包含当前情况却包含了. 转移的下一个状态v对于f1的修改情况,我们这里采用减法操作,但是一定要判断这一位上是否有1再减