最小费用最大流 ---- 2017icpc青岛现场赛 K Our Journey of Xian Ends (拆点控制原图点度 + 中间必经过的点设置成源点 + 起点设成汇点)

news/2024/7/2 23:20:57

题目链接


题目大意:

题目贼恶心难读
就是你出发地是"Xian"西安,现在你要出发到上海然后再去青岛,然后回到上海

飞机场限制:就是每个机场只能降落和起飞一次

上海的限制:上海有两个机场,叫虹桥和浦东机场,你要是要是降落在浦东机场只能到虹桥出发去青岛并且你最后还要回到虹桥再回到浦东!!
如果是降落在虹桥就没有限制,你最后回到浦东机场就好了

给你所有的航线信息:问你最小花费是多少?


解题思路:

首先要最小花费那么肯定要最小费用流

对于每个飞机场只能起飞降落一次我们可以进行拆点进行限制:
每个点uuu拆成u和u′u和u'uu分别是入点和出点表示之间连接流量为1,费用为0的边

然后就是我们看看路线有多少种?

  1. 西安->虹桥->青岛->浦东
  2. 西安->浦东->虹桥->青岛->虹桥->浦东

那么就是两种路径
我们是不是把在原图建立双向边然后跑最大流就好了呢?源点连向西安,汇点连向上上海呢?
肯定不是!!
我们看看这样跑出什么结果!!

在这里插入图片描述
它会跑出直接从西安到浦东的结果的最大流那就不对了无法确定是否经过青岛?

我们观察一下合法路径长啥样?
在这里插入图片描述
想想我们之前的建图是不不保证一定经过青岛
那么我们可以这样给青岛连一个源点
那么整个图就会被切成两部分,然后我们再给浦东和虹桥连接汇点,那么最大流跑出来的结果就是上半部分的选的路径拼下半边的路径:就是青岛到虹桥的路径和浦东的路径+西安到这两个点的路径
本质上就是只考虑路径覆盖不考虑路径方向
在这里插入图片描述

通过观察上图
首先我们知道青岛出发要发出两条边那么源点向青岛发出的流量是2
西安只选一个方向走那么源点向西安的发的流量就是1

然后你观察上面两个汇点虹桥和浦东,虹桥无论无何都要两条边,那么它向汇点连流量为2的边,浦东最多连接1条边那么就是连接流量为1的边

其他的边就是把点拆成两个就行了!!建的图和原图是一样的


AC code

#include<bits/stdc++.h>
using namespace std;
const int maxn=2e4+8;
const int INF=0x7f7f7f7f;
struct fuck{int u,v,cap,w,next;
}edge[maxn<<4];
int head[maxn<<1];
int tol;
void init()
{tol=0;memset(head,-1,sizeof(head));
}
void addedge(int u,int v,int w,int cap)
{edge[tol].u=u;edge[tol].v=v;edge[tol].cap=cap;edge[tol].w=w;edge[tol].next=head[u];head[u]=tol++;edge[tol].u=v;edge[tol].v=u;edge[tol].w=-w;edge[tol].cap=0;edge[tol].next=head[v];head[v]=tol++;
}
map<string,int> mp;
int idx;
int getid(char s[])
{if(mp.count(s)!=0)return mp[s];mp[s]=idx;addedge(idx*2-1,idx*2,0,1);idx++;return idx-1;
}
int dis[maxn<<1],pre[maxn<<1];
bool vis[maxn<<1];
bool spfa(int sour,int sink)
{queue<int>    q;q.push(sour);memset(dis,INF,sizeof(dis));memset(vis,false,sizeof(vis));dis[sour]=0;vis[sour]=true;pre[sour]=-1;int i,u,v;while(!q.empty()){u=q.front();q.pop();vis[u]=false;for(i=head[u];i!=-1;i=edge[i].next){v=edge[i].v;if(edge[i].cap>0&&edge[i].w+dis[u]<dis[v]){dis[v]=dis[u]+edge[i].w;pre[v]=i;if(!vis[v])vis[v]=true,q.push(v);}}}if(dis[sink]>=INF)   return false;return true;
}
void Minicost(int sour,int sink)
{int co,fl;co=fl=0;while(spfa(sour,sink)){int mi=INF;for(int i=pre[sink];i!=-1;i=pre[edge[i^1].v]){if(mi>edge[i].cap)mi=edge[i].cap;}for(int i=pre[sink];i!=-1;i=pre[edge[i^1].v]){edge[i].cap-=mi;edge[i^1].cap+=mi;}fl+=mi;co+=dis[sink]*mi;}if(fl==3)printf("%d\n",co);elseprintf("-1\n");
}
int main()
{int t;scanf("%d",&t);while(t--){int m;scanf("%d",&m);init();idx=1;mp.clear();mp["Xian"]=idx;addedge(idx*2-1,idx*2,0,1);idx++;mp["Qingdao"]=idx;addedge(idx*2-1,idx*2,0,2);idx++;mp["Hongqiao"]=idx;addedge(idx*2-1,idx*2,0,2);idx++;mp["Pudong"]=idx;addedge(idx*2-1,idx*2,0,1);idx++;while(m--){char s[12],c[12];int w;scanf("%s%s%d",s,c,&w);int u=getid(s);int v=getid(c);addedge(u*2,v*2-1,w,INF);addedge(v*2,u*2-1,w,INF);}int sour=0,sink=idx*2-1;addedge(sour,3*2-1,0,2);addedge(sour,4*2-1,0,1);addedge(1*2,sink,0,1);addedge(2*2,sink,0,2);Minicost(sour,sink);}return 0;
}

http://lihuaxi.xjx100.cn/news/285932.html

相关文章

koa-grace:一个基于koa的node多应用MVC框架

春节期间没回家留在北京写了一个基于koa的node MVC框架&#xff1a;koa-grace &#xff0c;大家有兴趣可以star & fork下&#xff0c;谢谢支持啦&#xff01;&#xff01; 项目地址&#xff1a; https://github.com/xiongwilee/koa-grace 详细文档&#xff1a; 1. 简介 koa…

07-图6 旅游规划 (25分)(以此感谢zyx佬)

这个题的话算是模板题改编了一点吧&#xff0c;不过个人感觉这个改编很有助于你理解迪杰斯特拉这个算法的真谛。 题解&#xff1a;新开一个cost数组来记录花费&#xff0c;仍然是用了优先队列优化的一个思想&#xff0c;与模板题不同的是只需要加一句话&#xff08;感谢zyx佬发…

百度Apollo 3.5是如何设计Cyber RT计算框架的?

自百度Apollo自动驾驶平台开源以来&#xff0c;已快速迭代至 3.5 版本&#xff0c;代码行数超过 39 万行&#xff0c;合作伙伴超过 130 家&#xff0c;吸引了来自 97 个国家的超 15000 名开发者。无疑&#xff0c;Apollo 是目前世界范围内最活跃的自动驾驶开放平台之一。最新发…

有没有必要把机器学习算法自己实现一遍?

编辑&#xff1a;机器学习算法与自然语言处理-忆臻&#xff0c;Charlotte数据挖掘-小杜https://www.zhihu.com/question/36768514作者&#xff1a;微调https://www.zhihu.com/question/36768514/answer/376510114不少自学的朋友很容易陷入到焦虑当中&#xff0c;尤其是在学习理…

Chapter 3、Java语法基础(二)----Java基本数据类型、变量与常量 (20th,Feb)

基本数据类型 1、整数类型 整数类型用来储存整数数值&#xff0c;即没有小数部分的数值&#xff0c;可以使正数、负数&#xff0c;也可以是零。根据所占内存的大小不同&#xff0c;分为byte、short、int、long 4种类型。 Byte型 整型中所分配内存空间最少的&#xff0c;只分配1…

后缀数组 + Hash + 二分 or Hash + 二分 + 双指针 求 LCP ---- 2017icpc 青岛 J Suffix (假题!!)

题目链接 题目大意&#xff1a; 就是给你n个串每个串取一个后缀,要求把串拼起来要求字典序最小&#xff01;&#xff01; sum_length_of_n≤5e5sum\_length\_of\_n\leq 5e5sum_length_of_n≤5e5 MY Slove : 首先我们知道对于最后一个串肯定是取最小后缀的 那么我们可以把最后…

第2关:实现一个链接存储的栈

#if !defined(LINKED_STACK_H_985552) #define LINKED_STACK_H_985552 typedef int T; //数据元素类型 struct LNode {T data;LNode* next; };struct LinkStack {LNode* top; // 栈顶指针int len; // 栈的长度 };LinkStack* LS_Create(); void LS_Free(LinkStack* ls); void LS…

最常用 150 个Linux命令汇总(建议收藏)

点击上方[视学算法]→右上角[...]→[设为星标⭐]来源&#xff1a;banana 童www.cnblogs.com/bananaaa/p/7774467.htmllinux 命令是对 Linux 系统进行管理的命令。对于 Linux 系统来说&#xff0c;无论是中央处理器、内存、磁盘驱动器、键盘、鼠标&#xff0c;还是用户等都是文件…