zoukankan      html  css  js  c++  java
  • 洛谷 P2747 [USACO5.4]周游加拿大Canada Tour 解题报告

    P2747 [USACO5.4]周游加拿大Canada Tour

    题目描述

    你赢得了一场航空公司举办的比赛,奖品是一张加拿大环游机票。旅行在这家航空公司开放的最西边的城市开始,然后一直自西向东旅行,直到你到达最东边的城市,再由东向西返回,直到你回到开始的城市。除了旅行开始的城市之外,每个城市只能访问一次,因为开始的城市必定要被访问两次(在旅行的开始和结束)。

    当然不允许使用其他公司的航线或者用其他的交通工具。

    给出这个航空公司开放的城市的列表,和两两城市之间的直达航线列表。找出能够访问尽可能多的城市的路线,这条路线必须满足上述条件,也就是从列表中的第一个城市开始旅行,访问到列表中最后一个城市之后再返回第一个城市。

    输入输出格式

    输入格式:

    第 1 行: 航空公司开放的城市数 (N) 和将要列出的直达航线的数量 (V)(N) 是一个不大于 100 的正整数。(V) 是任意的正整数。

    第 2..(N)+1 行: 每行包括一个航空公司开放的城市名称。城市名称按照自西向东排列。不会出现两个城市在同一条经线上的情况。每个城市的名称都 是一个字符串,最多15字节,由拉丁字母表上的字母组成;城市名称中没有空格。

    (N+2)..N+2+V-1$ 行: 每行包括两个城市名称(由上面列表中的城市名称组成),用一个空格分开。这样就表示两个城市之间的直达双程航线。

    输出格式:

    Line 1: 按照最佳路线访问的不同城市的数量 M。如果无法找到路线,输出 1。


    没想到DP怎么做,于是费用流暴力

    发现回来的路其实等价于去的路

    建图
    1.拆点,费1流1
    2.1号和n号点多一条费0流1的点,表示跑两次
    3.按原图连边,费0流1


    Code:

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <queue>
    #include <map>
    using namespace std;
    const int N=502;
    const int M=30000;
    int head[N],to[M],Next[M],edge[M],cost[M],cnt=1;
    void add(int u,int v,int w,int c)
    {
        to[++cnt]=v;edge[cnt]=w;cost[cnt]=c;Next[cnt]=head[u];head[u]=cnt;
        to[++cnt]=u;edge[cnt]=0;cost[cnt]=-c;Next[cnt]=head[v];head[v]=cnt;
    }
    map <string,int > ma;
    int n,m,s,t;
    void init()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
        {
            string name;
            cin>>name;
            ma[name]=i;
            add(i,i+n,1,1);
        }
        s=1,t=n<<1;
        add(s,s+n,1,0);
        add(t-n,t,1,0);
        for(int i=1;i<=m;i++)
        {
            string u,v;
            cin>>u>>v;
            if(ma[u]>ma[v])
                swap(u,v);
            add(ma[u]+n,ma[v],1,0);
        }
    }
    int dis[N],pre[N],used[N];
    bool spfa()
    {
        queue <int > q;
        memset(dis,-0x3f,sizeof(dis));
        int inf=dis[s];
        dis[s]=0;
        q.push(s);
        while(!q.empty())
        {
            int u=q.front();
            q.pop();
            used[u]=0;
            for(int i=head[u];i;i=Next[i])
            {
                int v=to[i],c=cost[i],w=edge[i];
                if(w&&dis[v]<dis[u]+c)
                {
                    pre[v]=i;
                    dis[v]=dis[u]+c;
                    if(!used[v])
                    {
                        used[v]=1;
                        q.push(v);
                    }
                }
            }
        }
        return dis[t]!=inf;
    }
    void work()
    {
        int maxcost=0,maxflow=0;
        while(spfa())
        {
            maxcost+=dis[t];
            maxflow++;
            int now=t;
            while(pre[now])
            {
                edge[pre[now]]-=1;
                edge[pre[now]^1]+=1;
                now=to[pre[now]^1];
            }
        }
        if(maxflow!=2) printf("1
    ");
        else printf("%d
    ",maxcost);
    }
    int main()
    {
        init();
        work();
        return 0;
    }
    

    2018.8.2

  • 相关阅读:
    POJ 3114 Tarjan+Dijkstra
    278. First Bad Version
    209. Minimum Size Subarray Sum
    154. Find Minimum in Rotated Sorted Array II
    153. Find Minimum in Rotated Sorted Array
    710. Random Pick with Blacklist
    767. Reorganize String
    524. Longest Word in Dictionary through Deleting
    349. Intersection of Two Arrays
    350. Intersection of Two Arrays II
  • 原文地址:https://www.cnblogs.com/butterflydew/p/9409382.html
Copyright © 2011-2022 走看看