网络流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[maxn];
const int inf = 0x3f3f3f3f;
int head[maxn*2];
int tot = 0;
struct edge{
    int v,nex,w,c;
}e[maxn*maxn*2];
void addedge(int u,int v,int w,int c){
    e[tot] = (edge){v,head[u],w,c,};
    head[u] = tot++;
    e[tot] = (edge){u,head[v],0,-c,};
    head[v] = tot++;
}
int dis[maxn*2];
int vis[maxn*2];
int pre[maxn*2];
bool spfa(int S,int T){
    memset(dis,0x3f,sizeof(dis));
    memset(vis,0,sizeof(vis));
    queue<int> q;
    q.push(S);
    dis[S] = 0;
    vis[S] = 1;
    while(!q.empty()){
        int now  = q.front();
        vis[now] = 0;
        q.pop();
        for(int i=head[now];i!=-1;i=e[i].nex){
            int v = e[i].v;
            int w = e[i].w;
            int c = e[i].c;
            if(w>0 && dis[v]>dis[now]+c){
                dis[v] = dis[now] +c;
                pre[v] = i;
                if(vis[v]==0){
                    vis[v] = 1;
                    q.push(v);
                }
            }
        }
    }
    if(dis[T]==0x3f3f3f3f) return false;
    return true;
}
int ed(int S,int T,int &flow){
    int p;
    int sum = 0;
    int maxflow = 0x3f3f3f3f;
    for(int i=T;i!=S;i=e[p^1].v){
        p = pre[i];
        maxflow = min(e[p].w,maxflow);
    }
    flow+=maxflow;
    for(int i=T;i!=S;i=e[p^1].v){
        p = pre[i];
        sum+=e[p].c*maxflow;
        e[p].w-=maxflow;
        e[p^1].w+=maxflow;
    }
    return sum;
}
int ans1[maxn];
int ans2[maxn];
int dfs(int now,int* p,int deep){
    p[deep] = now;
    for(int i=head[now];i!=-1;i=e[i].nex){
        int w = e[i^1].w;
        int v = e[i].v;
        if(w>0){
            e[i^1].w -=1;
            return dfs(e[i].v,p,deep+1);
        }
    }
    return deep+1;
}
    int n,v;
void solve(int S,int T){
    int flow = 0;
    int ans = 0;
    while(spfa(S,T)){
        ans+=ed(S,T,flow);
    }
    if(flow!=2) {
        cout<<"No Solution!"<<endl;
    }else{
        cout<<(-ans-2)<<endl;
        int k1,k2;
        k1 = dfs(1,ans1,0);
        k2 = dfs(1,ans2,0);
        for(int i=0;i<k1;i+=2){
            if(ans1[i]==T) continue;
            cout<<str[ans1[i]]<<endl;
        }
        for(int i=k2-1;i>=0;i-=2){
            if(ans2[i]==T) continue;
            if(ans2[i]==n) continue;
            cout<<str[ans2[i]]<<endl;
        }
    }
}
int main()
{
    memset(head,-1,sizeof(head));

    cin>>n>>v;
    int S = 0,T = 2*n+1;
    for(int i=1;i<=n;i++){
        cin>>str[i];
        mapp[str[i]] = i;
    }
    for(int i=1;i<=v;i++){
        string u,v;
        cin>>u>>v;
        addedge(mapp[u]+n,mapp[v],inf,0);
    }
    for(int i=2;i<n;i++){
        addedge(i,i+n,1,-1);
    }
    addedge(1,1+n,2,-1);
    addedge(n,n*2,2,-1);
    addedge(S,1,2,0);
    addedge(n*2,T,2,0);
    solve(S,T);
    return 0;
}

  

原文地址:https://www.cnblogs.com/tjucxz/p/8637642.html

时间: 2024-10-26 15:08:05

网络流24题11的相关文章

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

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

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

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

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

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

【网络流24题】 No.12 软件补丁问题(最小转移代价 最短路)

[题意] T 公司发现其研制的一个软件中有 n 个错误, 随即为该软件发放了一批共 m 个补丁程序. 每一个补丁程序都有其特定的适用环境, 某个补丁只有在软件中包含某些错误而同时又不包含另一些错误时才可以使用.一个补丁在排除某些错误的同时, 往往会加入另一些错误.换句话说, 对于每一个补丁 i, 都有 2 个与之相应的错误集合 B1[i]和 B2[i],使得仅当软件包含 B1[i]中的所有错误, 而不包含 B2[i]中的任何错误时, 才可以使用补丁 i. 补丁 i 将修复软件中的某些错误 F1[

BZOJ_1221_ [HNOI2001]_软件开发(网络流24题,最小费用流)

描述 http://www.lydsy.com/JudgeOnline/problem.php?id=1221 n天,每天需要r个毛巾,用完以后可以洗,要么花fa洗a天,要么花fb洗b天,毛巾不够了可以话f买一个,问最少需要多少钱. 分析 把每天拆成两个点:x[i]表示第i天的脏毛巾,y[i]表示第i天要用的毛巾. 1.s向x[i]连弧,容量为r[i],花费为0,表示每天会用脏r[i]条毛巾. 2.x[i]向x[i+1]连弧(注意边界),容量为INF,花费为0,表示把第i天的脏毛巾搁置到第i+1

[网络流24题]魔术球问题

问题描述: 假设有n根柱子,现要按下述规则在这n根柱子中依次放入编号为 1,2,3,4......的球. (1)每次只能在某根柱子的最上面放球. (2)在同一根柱子中,任何2个相邻球的编号之和为完全平方数. 试设计一个算法,计算出在n根柱子上最多能放多少个球.例如,在4 根柱子上最多可放11个球. ´编程任务: 对于给定的n,计算在 n根柱子上最多能放多少个球. ´数据输入: 文件第1 行有 1个正整数n,表示柱子数. ´结果输出: 文件的第一行是球数. 数据规模 n<=60  保证答案小于16

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??},和进行这些实验

[网络流24题] 搭配飞行员

14. [网络流24题] 搭配飞行员 ★★☆   输入文件:flyer.in   输出文件:flyer.out   简单对比时间限制:1 s   内存限制:128 MB [问题描述] 飞行大队有若干个来自各地的驾驶员,专门驾驶一种型号的飞机,这种飞机每架有两个驾驶员,需一个正驾驶员和一个副驾驶员.由于种种原因,例如相互配合的问题,有些驾驶员不能在同一架飞机上飞行,问如何搭配驾驶员才能使出航的飞机最多. 如图,假设有10个驾驶员,如图中的V1,V2,…,V10就代表达10个驾驶员,其中V1,V2,

网络流24题刷题记录

题目一:飞行员配对方案问题 一群飞行员和另一群飞行员之间有的可以配对,有的不能配对,求最多可以配多少对? 典型二分图最大匹配问题.可以用匈牙利算法 或者 加上源点汇点之后跑最大流.[感觉第二个打错的概率还低一些]. [还是介绍一下匈牙利算法吧][看白书大法好!] 从左边(s集)一个未盖点出发(还有没有和任何人匹配的点)出发,顺次经过未选边->选边->未选边.....[这样的路叫做交替路] 如果路径当中经过一个未盖点[这样的交替路叫增广路]...那么将所有的选边变成不选,不选的边选上,就可以多一