zoukankan      html  css  js  c++  java
  • 洛谷 P2469 [SDOI2010]星际竞速 解题报告

    题目描述

    10年一度的银河系赛车大赛又要开始了。作为全银河最盛大的活动之一,夺得这个项目的冠军无疑是很多人的梦想,来自杰森座α星的悠悠也是其中之一。

    赛车大赛的赛场由N颗行星和M条双向星际航路构成,其中每颗行星都有一个不同的引力值。大赛要求车手们从一颗与这N颗行星之间没有任何航路的天体出发,访问这N颗行星每颗恰好一次,首先完成这一目标的人获得胜利。

    由于赛制非常开放,很多人驾驶着千奇百怪的自制赛车来参赛。这次悠悠驾驶的赛车名为超能电驴,这是一部凝聚了全银河最尖端科技结晶的梦幻赛车。作为最高科技的产物,超能电驴有两种移动模式:高速航行模式和能力爆发模式。在高速航行模式下,超能电驴会展开反物质引擎,以数倍于光速的速度沿星际航路高速航行。在能力爆发模式下,超能电驴脱离时空的束缚,使用超能力进行空间跳跃——在经过一段时间的定位之后,它能瞬间移动到任意一个行星。

    天不遂人愿,在比赛的前一天,超能电驴在一场离子风暴中不幸受损,机能出现了一些障碍:在使用高速航行模式的时候,只能由每个星球飞往引力比它大的星球,否则赛车就会发生爆炸。

    尽管心爱的赛车出了问题,但是悠悠仍然坚信自己可以取得胜利。他找到了全银河最聪明的贤者——你,请你为他安排一条比赛的方案,使得他能够用最少的时间完成比赛。

                --by luogu

    http://daniu.luogu.org/problem/show?pid=2469



    一开始,并不知道怎么搞;

    后来听说和最小路径覆盖有关,然后就问了最小路径覆盖是怎么搞的......然后就想出来这题怎么做了;

    建图:

    • 拆点
    • S连所有一排点,1流0费;
    • S连所有二排点,1流跳跃的费用(1类边);
    • 一排点向有路径且可到达的点连边,1流路径费用(2类边);
    • 所有二排点连T点,1流0费;

    由于所有点至少可以跳跃到达,于是最大流为n,保证了遍历;

    考虑每个点的花费:

    1要么由跳跃到达,这样花费1类边,跳跃不受起点影响,所以可认为是从S跳过来的

    2要么由某个点经边到达,这样花费2类边,不管怎样边的起点一定到达过,于是直接从S连一排点,一排点连二排点

    对于2,细致的讨论一下:

    因为题目说编号对边方向有限制作用,于是不用担心边起点在终点遍历后再遍历

    本题与最小路径覆盖的相通之处——把路径拆成一条一条边,由于每条使用时都已经有了充足前置条件,所以可以这样做;

    代码如下:(极烂的代码,还是折叠了吧)

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 #define INF 2147483600
      5 using namespace std;
      6 int n,m,s,t;
      7 struct ss{
      8     int next,wi,fi,to,cp;
      9 }x[100001];
     10 int first[2001];
     11 int num;
     12 int dis[2001],vis[2001],pre[2001],way[2001],que[100001];
     13 int answ,ansf;
     14 void build(int ,int ,int ,int );
     15 int spfa();
     16 void EK();
     17 int main()
     18 {
     19     int i,j,k,l,o,m;
     20     scanf("%d%d",&n,&m);
     21     s=0,t=n<<1|1;
     22     for(i=1;i<=n;i++){
     23         scanf("%d",&j);
     24         build(s,i+n,1,j);
     25         x[num].cp=num+1;
     26         build(i+n,s,0,-j);
     27         x[num].cp=num-1;
     28         build(s,i,1,0);
     29         x[num].cp=num+1;
     30         build(i,s,0,0);
     31         x[num].cp=num-1;
     32         build(n+i,t,1,0);
     33         x[num].cp=num+1;
     34         build(t,n+i,0,0);
     35         x[num].cp=num-1;
     36     }
     37     for(i=1;i<=m;i++){
     38         scanf("%d%d%d",&j,&k,&o);
     39         if(j>k)
     40             swap(j,k);
     41         build(j,n+k,1,o);
     42         x[num].cp=num+1;
     43         build(n+k,j,0,-o);
     44         x[num].cp=num-1;
     45     }
     46     while(spfa())
     47         EK();
     48     printf("%d",ansf);
     49     return 0;
     50 }
     51 void build(int fr,int t,int w,int f){
     52     x[++num].next=first[fr];
     53     x[num].to=t;    x[num].fi=f;    x[num].wi=w;
     54     first[fr]=num;
     55 }
     56 int spfa(){
     57     int h=0,w=1,i;
     58     for(i=s;i<=t;i++)
     59         dis[i]=2147483647;
     60     memset(vis,0,sizeof(vis));
     61     memset(pre,-1,sizeof(pre));
     62     dis[s]=0;vis[s]=1;
     63     que[w]=s;
     64     while(h<w){
     65         h++;
     66         vis[que[h]]=0;
     67         i=first[que[h]];
     68         while(i){
     69             if(x[i].wi&&dis[x[i].to]>dis[que[h]]+x[i].fi){
     70                 dis[x[i].to]=dis[que[h]]+x[i].fi;
     71                 pre[x[i].to]=que[h];
     72                 way[x[i].to]=i;
     73                 if(vis[x[i].to]==0){
     74                   w++;
     75                   que[w]=x[i].to;
     76                   vis[que[w]]=1;
     77                 }
     78             }
     79             i=x[i].next;
     80         }
     81     }
     82     if(dis[t]!=2147483647)return 1;
     83     return 0;
     84 }
     85 void EK(){
     86     int i=t;
     87     int addf=0,addw=INF;
     88     while(pre[i]!=-1){
     89         if(x[way[i]].wi<addw)
     90             addw=x[way[i]].wi;
     91         i=pre[i];
     92     }
     93     i=t;
     94     while(pre[i]!=-1){
     95         addf+=x[way[i]].fi*addw;
     96         x[way[i]].wi-=addw;
     97         x[x[way[i]].cp].wi+=addw;
     98         i=pre[i];
     99     }
    100     answ+=addw;
    101     ansf+=addf;
    102 }

    祝AC

  • 相关阅读:
    图书管理系统---基于form组件和modelform改造添加和编辑
    Keepalived和Heartbeat
    SCAN IP 解释
    Configure Active DataGuard and DG BROKER
    Oracle 11gR2
    我在管理工作中積累的九種最重要的領導力 (李開復)
    公募基金公司超融合基础架构与同城灾备建设实践
    Oracle 11g RAC for LINUX rhel 6.X silent install(静默安装)
    11gR2 静默安装RAC 集群和数据库软件
    Setting Up Oracle GoldenGate 12
  • 原文地址:https://www.cnblogs.com/nietzsche-oier/p/6648421.html
Copyright © 2011-2022 走看看