2017ICPC青岛K Our Journey of Xian Ends

来源:互联网 发布:cf网截分析数据 编辑:程序博客网 时间:2024/05/18 01:12

Our Journey of Xian Ends
现场赛做到这题还剩1个多小时,首先心态就有些急了。
然后读题的时候比较急躁,题目又臭又长,导致没有发现,如果要在上海的两个机场之间走的话,只有一种走法。
但是由于要经过某两个特殊点,网赛有类似题,于是知道是费用流,先把板子敲上去,敲板子期间队友突然有建图的想法,然后让我来敲建图 。。。
期间一顿混乱,没能很好理解队友的意思,最后连样例都没过就GG了。
赛前准备了这么久的网络流最后还是没过,很是惭愧。

出来后大致听到了容量为2什么的东西,今天自己仔细想了想,如果题意理解清楚的话,其实并不是特别难。
有几点比较重要的地方。

此题其实只有两种走法
1. 西安-虹桥-青岛-浦东
2. 西安-浦东-虹桥-青岛-虹桥-浦东(上海的两个机场之间只有这一种走法,即先从浦东到虹桥,再从虹桥到浦东)
3. 还要注意拆点

这样一来就是经过了两个中间点的费用流。
可以发现,不管怎么样,从虹桥处都会连出两条边。那么把虹桥容量设为2,青岛也是一定会连出两条边,因此容量设为2,其他点连出的边都只有一条,因此容量都是1。

因为要在点上控制容量,因此要拆点,虹桥与青岛容量为2,其他都是1。

连边就是普通的连边,容量INF,因为有点控制流量,不用考虑边。

最后从源点向浦东连容量为1的边,向虹桥连容量为2的边,从终点向西安连容量为1的边,向青岛连容量为2的边,跑费用流即可,最大流为3时有解。

#include <iostream>#include <cstring>#include <cstdio>#include <algorithm>#include <queue>#include <map>using namespace std;const int MAXN = 10100;const int MAXM = 500000;const int INF = 0x3f3f3f3f;struct Edge{    int to,cap,flow,cost,nex;    Edge() {}    Edge(int to,int cap,int flow,int cost,int nex):to(to),cap(cap),flow(flow),cost(cost),nex(nex) {}}edge[MAXM];int dis[MAXN],tot,tol,head[MAXN],pre[MAXN],cnt,n;map<string,int> mp;bool vis[MAXN];struct node{    string ss1,ss2;    int co;}no[MAXN];void addedge(int u,int v,int cap,int cost){    edge[tol] = Edge(v,cap,0,cost,head[u]); head[u]=tol++;    edge[tol] = Edge(u,0,0,-cost,head[v]); head[v]=tol++;}void init(){    memset(head,-1,sizeof head);    cnt=tol=tot=0;    mp.clear();}bool spfa(int s,int t){    memset(vis,0,sizeof vis);    memset(pre,-1,sizeof pre);    memset(dis,0x3f,sizeof dis);    queue<int> que;    que.push(s);    dis[s] = 0;    while (!que.empty())    {        int u=que.front();que.pop();        vis[u] = false;        for (int i=head[u];~i;i=edge[i].nex)        {            int v=edge[i].to;            if (dis[v] > dis[u]+edge[i].cost && edge[i].cap>edge[i].flow)            {                dis[v] = dis[u] + edge[i].cost;                pre[v] = i;                if (!vis[v])                {                    vis[v]=true;                    que.push(v);                }            }        }    }    if (pre[t] != -1)        return true;    else        return false;}int MCMF(int s,int t,int &cost){    int flow=0;    cost=0;    while (spfa(s,t))    {        int tmp = INF;        for (int i=pre[t];~i;i=pre[edge[i^1].to])        {            tmp = min(tmp, edge[i].cap-edge[i].flow );        }        for (int i=pre[t];~i;i=pre[edge[i^1].to])        {            edge[i].flow += tmp;            edge[i^1].flow -= tmp;            cost += tmp*edge[i].cost;        }        flow += tmp;    }    return flow;}int main(){    int t;    scanf("%d",&t);    while (t--)    {        init();        scanf("%d",&n);        string ss1,ss2;        for (int i=1;i<=n;i++)        {            cin>>no[i].ss1>>no[i].ss2>>no[i].co;            ss1=no[i].ss1;ss2=no[i].ss2;            if (!mp[ss1]) mp[ss1] = ++cnt;            if (!mp[ss2]) mp[ss2] = ++cnt;        }        int xa=mp["Xian"],hq=mp["Hongqiao"],pd=mp["Pudong"],qd=mp["Qingdao"];//        printf("xa=%d hq=%d pd=%d qd=%d\n",xa,hq,pd,qd);        for (int i=1;i<=n;i++)        {            int a1=mp[no[i].ss1],a2=mp[no[i].ss2];            addedge(a1+cnt,a2,INF,no[i].co);            addedge(a2+cnt,a1,INF,no[i].co);        }        for (int i=1;i<=cnt;i++)        {            if (i == hq)            {                addedge(i,i+cnt,2,0);            }            else if (i == qd)            {                addedge(i,i+cnt,2,0);            }            else            {                addedge(i,i+cnt,1,0);            }        }        addedge(0,pd,1,0);        addedge(0,hq,2,0);        addedge(xa+cnt,2*cnt+1,1,0);        addedge(qd+cnt,2*cnt+1,2,0);        int cost,flow;        flow = MCMF(0,2*cnt+1,cost);        if (flow == 3)            printf("%d\n",cost);        else            printf("-1\n");    }    return 0;}
阅读全文
0 0
原创粉丝点击