2017 ACM 区域赛青岛站(现场赛) K Our Journey of Xian Ends
Life is a journey, and the road we travel has twists and turns, which sometimes lead us to unexpected places and unexpected people. Now our journey of Xian ends. To be carefully considered are the following questions.
A few months later in Qingdao, an essential ACM competition had been scheduled. But before the competition, we need to attend a wedding in Shanghai. And after the competition, we will leave the country from Shanghai, so Pudong International Airport (Pudong in short) is the end of our tour.
Here we have some vital information and missions we have to accomplish.
We have a VIP card of CNAC. For each airport we can enjoy the special VIP services in the departure floor and the arrival floor once respectively. For the pleasure of traveling, it is intolerant without VIP services. That is say that for each airport we can leave from it only once, but without regard to the last flight leaving the country from Pudong, Shanghai. Meanwhile, for each airport we can arrive at it only once.
All as we know, Shanghai has two airports, Hongqiao Airport (Hongqiao in short) and Pudong. Arriving at one and then leaving from another one is a spurned thing. But fortunately there is a nice and evil compensation service. Having a pair of transfer records between Hongqiao and Pudong in both directions, we can obtain a sensible compensation. Actually, we only consider planes in our tour, with the only exception in Shanghai. The exception is that we can arrive and leave Shanghai at different airports. However, if we decide so the compensation described above is necessary. Before the end of our tour, we will pass through Shanghai twice, once for the wedding and another time for the final departure. If we want to obtain the compensation, in the first time we must transfer from Pudong to Hongqiao, and in the second time we will transfer from Hongqiao to Pudong.
Similar transfers between airports in other city are not allowed. If we arrived at a city, we would not go to an airport in an adjacent city by car, bus or interurban railway as well.
Now, all available flights between airports are known. We have plenty of time yet. So we do not have any restriction about the number of times. What we require is the smallest total cost of flights throughout the whole tour.
Here we go.
Input
There are several test cases. The first line of input contains an integer t (1 ≤ t ≤ 160) which is the total number of test cases. For each test case, the first line contains an integer m (m ≤ 10000) which is the number of known flights. Each of the following m lines describes a flight which contains two string indicating the names of two airports and an integer between 1 and 255 indicating the cost. The flight connects two given airports and it is bidirectional. The name of each airport is an non-empty string with English letters that are no longer than 10. We use “Xian” to present the only airport in Xian, and use “Qingdao” to present the only airport in Qingdao. The airports in Shanghai are described as “Hongqiao” and “Pudong” respectively.
Output
For each test case, output the smallest total cost, or output −1 if it is impossible.
Sample Input
3
4
Xian Hongqiao 3
Xian Pudong 4
Qingdao Hongqiao 4
Qingdao Pudong 3
4
Xian Hongqiao 4
Xian Pudong 3
Qingdao Hongqiao 3
Qingdao Pudong 4
6
Xian Hongqiao 4
Xian Pudong 3
Qingdao Hongqiao 3
Qingdao Pudong 4
Qingdao Xuzhou 1
Xuzhou Hongqiao 1
Sample Output
10
9
8
题意: 有很多地方,你一开始在西安,然后你要到上海(浦东机场或者虹桥机场),然后飞到青岛,然后从青岛飞回上海。期间可以途径其他地方,但是每个地方都只能去一遍,只有上海能来两遍(每个机场来一遍),但是最后最终要回到上海浦东机场,浦东机场可以坐车到虹桥机场吗,但是虹桥机场不能坐车到浦东机场,问最后坐飞机的最小费用是多少。
思路: 最小费用最大流问题,难在建图上,我们发现他题目意思实际上就是只能从西安—》上海 上海虹桥出发——》青岛——》上海浦东,所以路是定死的。我们只要直接建图就好了。因为限制了每个地方只能去一次,所以我们只要拆点就好了,拆点的时候注意虹桥和青岛两个地方是要流经两次的,因为我们把上海作为源点,从青岛回上海等于从上海到青岛,所以青岛要两次,虹桥是因为出了本来就有的一次,从浦东还可以到虹桥机场,有一次,所以有两次。最后对于图中给出的边u->v,连u’->v和v’->u的费用为边权流量为INF的有向边,之后建一个源点连虹桥和浦东,费用均为0,但是连虹桥的流量为2,浦东的流量为1,再建一个汇点,连西安和青岛,同样费用均为0,但是连西安的流量为1,青岛的为2,好了,图建好了,直接跑一边费用流,如果最大流为3,就输出,否则就是-1;
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<map>
#include<queue>
using namespace std;
#define INF 0x3f3f3f3f
const int maxed=40000+10;
struct E
{
int from,to,cap,flow,cost;
};
struct MCMF
{
int n,m,s,t;
vector<E> edg;
vector<int> G[maxed];
int inq[maxed];
int d[maxed];
int p[maxed];
int a[maxed];
void init(int n)
{
this->n=n;
for(int i=0;i<=n;i++)
G[i].clear();
edg.clear();
}
void add_(int from,int to,int cap,int cost)
{
edg.push_back((E){from,to,cap,0,cost});
edg.push_back((E){to,from,0,0,-cost});
m=edg.size();
G[from].push_back(m-2);
G[to].push_back(m-1);
}
bool BellmanFord(int s,int t,int &flow,int &cost)
{
for(int i=0;i<=n;i++)
d[i]=INF;
memset(inq,0,sizeof(inq));
d[s]=0;inq[s]=1;p[s]=0;a[s]=INF;
queue<int> Q;
Q.push(s);
while(!Q.empty()){
int u=Q.front();
Q.pop();
inq[u]=0;
for(int i=0;i<G[u].size();i++){
E& e=edg[G[u][i]];
if(e.cap>e.flow&&d[e.to]>d[u]+e.cost){
d[e.to]=d[u]+e.cost;
p[e.to]=G[u][i];
a[e.to]=min(a[u],e.cap-e.flow);
if(!inq[e.to]){
Q.push(e.to);
inq[e.to]=1;
}
}
}
}
if(d[t]==INF)
return false;
flow+=a[t];
cost+=d[t]*a[t];
int u=t;
while(u!=s){
edg[p[u]].flow+=a[t];
edg[p[u]^1].flow-=a[t];
u=edg[p[u]].from;
}
return true;
}
int Mincost(int s,int t)
{
int flow=0,cost=0;
while(BellmanFord(s,t,flow,cost));
if(flow==3)
return cost;
return INF;
}
}mc;
map<string,int> ma;
int n;
int main()
{
std::ios::sync_with_stdio(false);
int N;
cin>>N;
while(N--){
ma.clear();
cin>>n;
mc.init(4*n+1);
int cnt=0,a;
string s1,s2;
for(int i=1;i<=n;i++){
cin>>s1>>s2>>a;
if(!ma.count(s1))
ma[s1]=++cnt;
if(!ma.count(s2))
ma[s2]=++cnt;
mc.add_(ma[s1]+2*n,ma[s2],INF,a);
mc.add_(ma[s2]+2*n,ma[s1],INF,a);
}
map<string,int>::iterator it;
for(it=ma.begin();it!=ma.end();it++){
if(it->first=="Xian"){
mc.add_(it->second+2*n,4*n+1,1,0);
mc.add_(it->second,it->second+2*n,1,0);
}
else if(it->first=="Qingdao"){
mc.add_(it->second+2*n,4*n+1,2,0);
mc.add_(it->second,it->second+2*n,2,0);
}
else if(it->first=="Hongqiao"){
mc.add_(0,it->second,2,0);
mc.add_(it->second,it->second+2*n,2,0);
}
else if(it->first=="Pudong"){
mc.add_(0,it->second,1,0);
mc.add_(it->second,it->second+2*n,1,0);
}
else{
mc.add_(it->second,it->second+2*n,1,0);
}
}
int answer=mc.Mincost(0,4*n+1);
if(answer==INF)
cout<<-1<<endl;
else
cout<<answer<<endl;
}
return 0;
}
链接:https://blog.csdn.net/wangshuhe963/article/details/78516821
//因为我本来就是看这个大佬转载的,代码就直接贴他的了