网络流24题-航空路线问题

航空路线问题

时空限制1000ms / 128MB

题目描述

给定一张航空图,图中顶点代表城市,边代表 2 城市间的直通航线。现要求找出一条满足下述限制条件的且途经城市最多的旅行路线。

(1)从最西端城市出发,单向从西向东途经若干城市到达最东端城市,然后再单向从东向西飞回起点(可途经若干城市)。

(2)除起点城市外,任何城市只能访问 1 次。

对于给定的航空图,试设计一个算法找出一条满足要求的最佳航空旅行路线。

输入输出格式

输入格式:

第 1 行有 2 个正整数 N 和 V,N 表示城市数,N<100,V 表示直飞航线数。

接下来的 N 行中每一行是一个城市名,可乘飞机访问这些城市。城市名出现的顺序是从西向东。也就是说,设 i,j 是城市表列中城市出现的顺序,当 i>j 时,表示城市 i 在城市 j 的东边,而且不会有 2 个城市在同一条经线上。城市名是一个长度不超过15 的字符串,串中的字符可以是字母或阿拉伯数字。例如,AGR34 或 BEL4。

再接下来的 V 行中,每行有 2 个城市名,中间用空格隔开,如 city1 city2 表示 city1到 city2 有一条直通航线,从 city2 到 city1 也有一条直通航线。

输出格式:

件第 1 行是旅行路线中所访问的城市总数 M。 接下来的 M+1 行是旅行路线的城市名,每行写 1 个城市名。首先是出发城市名,然后按访问顺序列出其它城市名。 注意,最后 1 行(终点城市)的城市名必然是出发城市名。如果问题无解,则输出“No Solution!”。

输入输出样例

输入样例:

8 9
Vancouver
Yellowknife
Edmonton
Calgary
Winnipeg
Toronto
Montreal
Halifax
Vancouver Edmonton
Vancouver Calgary
Calgary Winnipeg
Winnipeg Toronto
Toronto Halifax
Montreal Halifax
Edmonton Montreal
Edmonton Yellowknife
Edmonton Calgary

输出样例:

7
Vancouver
Edmonton
Montreal
Halifax
Toronto
Winnipeg
Calgary
Vancouver 

说明

题目链接:https://www.luogu.org/problemnew/show/P2770


最大权不相交路径。一开始我没想到竟然可以看成从左端点开始的两条不相交路径,瞎搞了好久。。。

#include<bits/stdc++.h>
#define INF LLONG_MAX/2
#define N 205
using namespace std;

struct ss
{
    int u,v,next;
    long long flow,cost;
};

ss edg[N*N];
int head[N],now_edge=0;

void addedge(int u,int v,long long flow,long long cost)
{
    cost=-cost;
    edg[now_edge]=(ss){u,v,head[u],flow,cost};
    head[u]=now_edge++;
    edg[now_edge]=(ss){v,u,head[v],0,-cost};
    head[v]=now_edge++;
}

int spfa(int s,int t,long long &flow,long long &cost)
{
    int vis[N]={0};
    vis[s]=1;
    queue<int>q;
    q.push(s);
    long long dis[N];
    for(int i=0;i<N;i++)dis[i]=INF;
    dis[s]=0;
    int pre[N]={0};
    long long addflow[N]={0};
    addflow[s]=INF;

    while(!q.empty())
    {
        int now=q.front();
        q.pop();
        vis[now]=0;

        for(int i=head[now];i!=-1;i=edg[i].next)
        {
            ss e=edg[i];
            if(e.flow>0&&dis[e.v]>dis[now]+e.cost)
            {
                dis[e.v]=dis[now]+e.cost;
                pre[e.v]=i;
                addflow[e.v]=min(e.flow,addflow[now]);
                if(!vis[e.v])
                {
                    q.push(e.v);
                    vis[e.v]=1;
                }
            }
        }
    }

    if(dis[t]==INF)return 0;

    flow+=addflow[t];
    cost+=addflow[t]*dis[t];

    int now=t;
    while(now!=s)
    {
        edg[pre[now]].flow-=addflow[t];
        edg[pre[now]^1].flow+=addflow[t];
        now=edg[pre[now]].u;
    }
    return 1;

}

void mcmf(int s,int t,long long &flow,long long &cost)
{
    while(spfa(s,t,flow,cost));
}

void init()
{
    now_edge=0;
    memset(head,-1,sizeof(head));
}

map<string,int>Map1;
map<int,string>Map2;

vector<int>ans;
int n;

void dfs(int x)
{
    if(x==n)return;
    int u=x*2;
    for(int i=head[u];i!=-1;i=edg[i].next)
    {
        if(edg[i^1].flow&&edg[i].v!=u-1)
        {
            edg[i^1].flow--;
            ans.push_back(edg[i].v/2+1);
            dfs(edg[i].v/2+1);
            return;

        }
    }
}

int main()
{
    init();
    int m;
    scanf("%d %d",&n,&m);
    for(int i=1;i<=n;i++)
    {
        string a;
        cin>>a;
        Map1.insert(pair<string,int>(a,i));
        Map2.insert(pair<int,string>(i,a));
    }
    int s=2*n+1,t=s+1;

    while(m--)
    {
        string a,b;
        cin>>a>>b;
        int u=min(Map1[a],Map1[b]),v=max(Map1[a],Map1[b]);
        addedge(u*2,v*2-1,INF,0);
    }

    for(int i=2;i<n;i++)addedge(i*2-1,i*2,1,1);
    addedge(1,2,2,1);
    addedge(2*n-1,2*n,2,1);
    addedge(s,1,2,0);
    addedge(2*n,t,INF,0);

    long long flow=0,cost=0;
    mcmf(s,t,flow,cost);

    if(flow<2)
    {
        printf("No Solution!\n");
        return 0;
    }

    printf("%lld\n",-cost-2);

    dfs(1);
    cout<<Map2[1]<<endl;
    for(int i=0;i<ans.size();i++)cout<<Map2[ans[i]]<<endl;
    ans.clear();
    dfs(1);
    for(int i=ans.size()-2;i>=0;i--)cout<<Map2[ans[i]]<<endl;
    cout<<Map2[1]<<endl;
    return 0;

}

原文地址:https://www.cnblogs.com/tian-luo/p/9726804.html

时间: 2024-11-17 07:54:05

网络流24题-航空路线问题的相关文章

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

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

「网络流24题」 题目列表

「网络流24题」 题目列表 序号 题目标题 模型 题解 1 飞行员配对方案问题 二分图最大匹配 <1> 2 太空飞行计划问题 最大权闭合子图 <2> 3 最小路径覆盖问题 二分图最小路径覆盖 <3> 4 魔术球问题 <4> 5 圆桌问题 <5> 6 最长递增子序列问题 <6> 7 试题库问题 <7> 8 机器人路径规划问题 <8> 9 方格取数问题 二分图最大点权独立集 <9> 10 餐巾计划问题

网络流24题小结

网络流24题 前言 网络流的实战应用篇太难做了,因此先完善这一部分 ## 第一题:飞行员配对方案 \(BSOJ2542\)--二分图 最优匹配 题意 两国飞行员\(x\)集合\(y\)集合,\(x\)飞行员可以配对特定的\(y\)集合的飞行员(可无),求一对一配对最大数 Solution 二分图最大匹配裸题,最大流实现 建图:(设\(i\in x\)而\(i'\in y\)) \((S,i,1)~(i',T,1)\) 对\((i,j')\)可匹配\((i,j',1)\) Code 略 ## 第二

【线性规划与网络流24题】汽车加油行驶问题 分层图

汽车加油行驶问题 Time Limit: 1 Sec  Memory Limit: 128 MB Description 给定一个 N*N的方形网格,设其左上角为起点◎,坐标为( 1,1),X轴向右为正, Y轴向下为正,每一个方格边长为 1,如图所看到的.一辆汽车从起点◎出发驶向右下角终点▲,其坐标为( N,N).在若干个网格交叉点处,设置了油库,可供汽车在行驶途中加油.汽车在行驶过程中应遵守例如以下规则: (1)汽车仅仅能沿网格边行驶,装满油后能行驶 K条网格边.出发时汽车已装满油,在起点与终

【网络流24题----14】孤岛营救问题

孤岛营救问题 Time Limit: 1 Sec  Memory Limit: 128 MB Description 1944年,特种兵麦克接到国防部的命令.要求马上赶赴太平洋上的一个孤岛,营救被敌军俘虏的大兵瑞恩.瑞恩被关押在一个迷宫里,迷宫地形复杂,但幸好麦克得到了迷宫的地形图.迷宫的外形是一个长方形,其南北方向被划分为 N行,东西方向被划分为 M列,于是整个迷宫被划分为 N×M个单元.每个单元的位置可用一个有序数对 (单元的行号,单元的列号)来表示.南北或东西方向相邻的 2个单元之间可能互

【网络流24题】

网络流 网络流24题 [最小路径覆盖问题] 关于输出路径,因为即使有反向弧经过左侧点也一定会改变左侧点的去向,若没连向右侧就会被更新到0,所以不用在意. mark记录有入度的右侧点,然后从没入度的右侧点开始把整条路径输出来即可. #include<cstdio> #include<algorithm> #include<cstring> using namespace std; const int maxn=100000,inf=0x3f3f3f3f; int n,m,

【网络流24题】魔术球问题

P1226 - [网络流24题]魔术球问题 Description 假设有n根柱子,现要按下述规则在这n根柱子中依次放入编号为 1,2,3,4......的球. (1)每次只能在某根柱子的最上面放球. (2)在同一根柱子中,任何2个相邻球的编号之和为完全平方数. 试设计一个算法,计算出在n根柱子上最多能放多少个球.例如,在4 根柱子上最多可 放11个球. ′编程任务: 对于给定的n,计算在 n根柱子上最多能放多少个球. Input 第1 行有 1个正整数n,表示柱子数. Output 第一行是球

AC日记——[网络流24题]骑士共存 cogs 746

746. [网络流24题] 骑士共存 ★★☆   输入文件:knight.in   输出文件:knight.out   简单对比时间限制:1 s   内存限制:128 MB 骑士共存问题 «问题描述: 在一个n*n个方格的国际象棋棋盘上,马(骑士)可以攻击的棋盘方格如图所示.棋盘 上某些方格设置了障碍,骑士不得进入. «编程任务: 对于给定的n*n个方格的国际象棋棋盘和障碍标志,计算棋盘上最多可以放置多少个骑 士,使得它们彼此互不攻击. «数据输入: 由文件knight.in给出输入数据.第一行

网络流24题

刷刷基础题来巩固一下基础.. #1.飞行员配对方案问题 pdf链接 听说各大OJ的题面都和pdf不同.. 嗯连边匹配就行.. #include <cstdio> #include <cstring> #include <cstdlib> #include <algorithm> #include <queue> using namespace std; const int Maxn = 110; struct node { int y, next