计蒜客 菜鸟物流的运输网络 解题报告
来源:互联网 发布:weui商城模板源码 编辑:程序博客网 时间:2024/05/01 00:59
菜鸟物流有自己的运输网络,网络中包含 nn 个城市物流集散中心,和m 对城市之间的运输线路(线路是双向的)。菜鸟物流允许淘宝卖家自行确定包裹的运输路径,但只有一条限制规则:不允许经过重复的城市。淘宝卖家小明从a 城市寄出快递后,希望包裹在 mid 城市进行包装加工以后再寄往 b 城市。
现在小明希望算出一个满足他需求的合法运输路径,你可以帮他算出来么?
已知这样的方案一定存在。请为小明输出任意一个可行方案。
输入格式
第一行一个正整数 T(1≤T≤10)T(1 \leq T \leq 10)T(1≤T≤10) 表示数据的组数。
每组数据第一行 2 个正整数n,m(3≤n≤100,m≤n(n−1)2)n,m(3 \leq n \leq 100,m \leq \frac{n(n-1)}{2})n,m(3≤n≤100,m≤2n(n−1)),表示城市个数和运输线路数目。
第二行 3 个互不相同正整数a,b,mid(1≤a,b,mid≤n)a,b,mid(1 \leq a,b,mid \leq n)a,b,mid(1≤a,b,mid≤n),表示起点、终点和途径城市。
接下来 m 行,每行2 个正整数x,y(1≤x,y≤n)x,y(1\leq x,y \leq n)x,y(1≤x,y≤n),表示每条线路连接的2 个城市。
每组数据一定存在至少一组合法方案。如果有多种满足小明需求的合法运输路径,输出任意一个即可。
输出格式
每组数据输出 L 个正整数,表示顺次经过的城市的编号,包括起点和终点。每两个整数之间一个空格,最后一个整数后面没有空格。
样例输入
15 51 5 31 22 33 44 55 1
样例输出
1 2 3 4 5
中文题目,就不多赘述了。
大致思路如下:
因为每个点都只能经过一次,所以解决方案是对于每个点先进行拆点,然后以mid为起点,a,b为终点建图跑网络流,然后找路径
具体思路如下:
1.拆点:
对于一个点A都可以把和它连着的路理解为有通向它的路和它通向的路,然后把通向它的路全部连到一个节点A1,它通向的路连到一个节点A2,然后让这两个节点之间连一条流为1的单向网络流。这样对于一个需要经过A点的路就从X->A->Y变成了X->A1->(这是一条从A1到A2的流为1的流)A2->Y;于是由于A1->A2的流为1所以A1->A2就只能被用一次,就保证了A只能被用一次了。
2.建图:
因为是双向边,从起点跑到mid是等价于从mid跑到起点的所以不妨把图看作从mid跑到起点和终点各一次同时保证每个点只经过一次,每个点只经过一次可以由拆点完成,然后给mid一个流为2的流,设计一个超级汇点,让起点和终点都能够流向超级汇点1的流量。 然后就可以跑网络流了
3.寻找路径:
在跑了网络流之后若G[i][j]有值那么其实说明跑过一条从j到i的流(这里要注意,如果G[i][j]和G[j][i]都有值其实相当于没有跑过),然后按照想要的输出顺序存到vector里面再读取就好了
代码如下:
#include <bits/stdc++.h>#define inf 1000007using namespace std ;int G[305][305],layer[305];int n,m,a,b,mid,E;vector<int>ans;bool find_layer(){ memset(layer,-1,sizeof(layer)); queue<int>q; q.push(0); layer[0]=0; while(!q.empty()){ int now=q.front(); q.pop(); for(int i=1;i<=E;i++){ if(G[now][i] && layer[i]==-1){ layer[i]=layer[now]+1; q.push(i); if(i==E)return true; } } } return false;}void dinic(){ int vis[305]; deque<int>dq; while(!dq.empty())dq.pop_front(); while(find_layer()){ memset(vis,0,sizeof(vis)); getchar(); vis[0]=1; dq.push_back(0); while(!dq.empty()){ if(dq.back()==E){ int Min=inf,Min_s; for(int i=1;i<dq.size();i++){ int s=dq[i-1],e=dq[i]; if(Min>G[s][e]){ Min=G[s][e]; Min_s=s; } } for(int i=1;i<dq.size();i++){ int s=dq[i-1],e=dq[i]; G[s][e]-=Min; G[e][s]+=Min; } while(!dq.empty() && dq.back()!=Min_s){ vis[dq.back()]=0; dq.pop_back(); } } else{ int flag=1; for(int i=1;i<=E;i++){ if(G[dq.back()][i] && !vis[i] && layer[i]==layer[dq.back()]+1){ flag=0; vis[i]=1; dq.push_back(i); break; } } if(flag)dq.pop_back(); } } }}void solve(){ int s=a; queue<int >q; while(!q.empty())q.pop(); q.push(s); while(!q.empty()){//保存从a到mid的路径 int now=q.front(); q.pop(); if(now!=mid)//没有这个特判的话mid会被放两次 ans.push_back(now); for(int i=1;i<=n;i++){ if(G[now+n][i] && !G[i+n][now]){ G[now+n][i]=0; q.push(i); } } } while(!q.empty())q.pop(); q.push(mid); while(!q.empty()){//保存mid到b的路径 int now=q.front(); q.pop(); ans.push_back(now); for(int i=1;i<=n;i++){ if(G[i+n][now] && !G[now+n][i]){ G[i+n][now]=0; q.push(i); } } } printf("%d",*ans.begin()); for(vector<int>::iterator it=ans.begin()+1;it!=ans.end();it++){ printf(" %d",*it); } printf("\n");}int main(){ int test; scanf("%d",&test); while(test--){ memset(G,0,sizeof(G)); scanf("%d%d%d%d%d",&n,&m,&a,&b,&mid); E=n*2+1;//设置超级汇点 for(int i=1;i<=m;i++){ int s,e; scanf("%d%d",&s,&e); G[s+n][e]=G[e+n][s]=1;//对于每个点都拆成i和i+n } for(int i=1;i<=n;i++)G[i][i+n]=1; G[0][mid]=2;G[mid][mid+n]=2; G[a+n][E]=1;G[b+n][E]=1; dinic(); ans.clear(); solve(); } return 0;}
- 计蒜客 菜鸟物流的运输网络 解题报告
- 计蒜客 菜鸟物流的运输网络
- 计蒜客 菜鸟物流的运输网络
- 计蒜之道复赛F题 菜鸟物流的运输网络(网络流)
- [网络流] 2016 计蒜之道 复赛 菜鸟物流的运输网络
- 计蒜之道 2016 复赛 F.菜鸟物流的运输网络
- 2016计蒜之道复赛 菜鸟物流的运输网络
- 2016 计蒜之道 复赛 菜鸟物流的运输网络【拆点+思维建图+网络流】
- noip2015运输计划解题报告
- zoj1005解题报告---菜鸟的第一篇解题报告
- 物流运输
- Code[VS] 1669 运输装备 解题报告
- [ZJOI2012]网络 解题报告
- 【SPFA+DP】物流运输
- 【ZJOI2006】物流运输trans
- 【ZJOI2006】物流运输
- 【BZOJ1003】物流运输trans
- [ZJOI2006]物流运输trans
- 关于map 以及 hash_map
- C++11/14/17 auto & decltype
- 散列表冲突解决方法11.1.3
- 基础queue优先队列
- 按体质吃哪个(夏天)
- 计蒜客 菜鸟物流的运输网络 解题报告
- 为什么揉
- c# 选择结构与循环结构
- c# as is 的区别
- stack(栈)
- MySQL的导入和导出
- [李景山php] 深入理解PHP内核[读书笔记]--第四章:函数的实现 --函数的返回值
- SSH整合:No Spring WebApplicationInitializer types detected on classpath
- html为图像添加超链接