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.

樣例輸入

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

樣例輸出

10
9
8

題意:有三個城市:西安,上海,青島,現在要求在這三個城市之間往返,要求先從西安到上海,再從上海到青島,再從青島到上海,問最小花費,每個城市只有一個機場因此只能走一次,但上海有兩個機場:虹橋機場和浦東機場,又因爲上海有兩個機場,所以這裏有一個限定條件:只允許從浦東機場前往虹橋機場,也就是說如果從西安來的某條路線到達浦東機場,那麼將有兩種選擇,一種去虹橋機場出發,另一種從浦東出發,但是如果西安的某條路線到達虹橋機場,那麼將只有一種選擇,從虹橋機場出發;

思路:裸的最小費用流問題,但是建圖是個難點,我沒有參加現場賽,真的不知道能否在現場那種環境下A出來,其實思路還是不難得,首先因爲每個城市只能走一次,所以拆點,把每個城市拆成u和u',然後連u->u'費用爲0,流量爲1的邊,但是這裏要注意,青島這個點和虹橋這個點要連流量爲2,費用爲0的邊,因爲虹橋和青島這裏都是兩次經過的點,仔細一想就不難想到這樣的可行性,然後對於圖中給出的邊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;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章