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

  • 相关阅读:
    125、TensorFlow计算图的执行
    123、TensorFlow的Job
    122、TensorFlow多设备运行
    121、TensorFlow张量命名
    关于CSRF跨域请求伪造的解决办法
    angular基于ui-router实现系统权限控制
    gulp自动化打包及静态文件自动添加版本号
    深入研究HTML5实现图片压缩上传
    移动web模拟客户端实现多方框输入密码效果
    高级功能:很有用的javascript自定义事件
  • 原文地址:https://www.cnblogs.com/butterflydew/p/9409382.html
Copyright © 2011-2022 走看看