zoukankan      html  css  js  c++  java
  • [Sdoi2010]星际竞速

    个人对山东省选已经十分无语了,做了三道题,都TM是费用流,这山东省选是要干什么,2009--2011连续三年,只要会费用流,然后建个边,跑一跑就过了。

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

    赛车大赛的赛场由 N 颗行星和M条双向星际航路构成,其中每颗行星都有一个不同的引力值。大赛要求车手们从一颗与这 N 颗行星之间没有任何航路的天体出发,访问这 N 颗行星每颗恰好一次,首先完成这一目标的人获得胜利。
    由于赛制非常开放,很多人驾驶着千奇百怪的自制赛车来参赛。这次悠悠驾驶的赛车名为超能电驴,这是一部凝聚了全银河最尖端科技结晶的梦幻赛车。作为最高科技的产物,超能电驴有两种移动模式:高速航行模式和能力爆发模式。在高速航行模式下,超能电驴会展开反物质引擎,以数倍于光速的速度沿星际航路高速航行。在能力爆发模式下,超能电驴脱离时空的束缚,使用超能力进行空间跳跃——在经过一段时间的定位之后,它能瞬间移动到任意一个行星。
    天不遂人愿,在比赛的前一天,超能电驴在一场离子风暴中不幸受损,机能出现了一些障碍:在使用高速航行模式的时候,只能由每个星球飞往引力比它大的星球,否则赛车就会发生爆炸。
    尽管心爱的赛车出了问题,但是悠悠仍然坚信自己可以取得胜利。他找到了全银河最聪明的贤者——你,请你为他安排一条比赛的方案,使得他能够用最少的时间完成比赛。

    输入描述 Input Description

    第一行是两个正整数 N, M。
    第二行 N 个数 A1~AN, 其中Ai表示使用能力爆发模式到达行星 i 所需的定位
    时间。
    接下来 M行,每行 3个正整数ui, vi, wi,表示在编号为 ui和vi的行星之间存在一条需要航行wi时间的星际航路。
    输入数据已经按引力值排序,也就是编号小的行星引力值一定小,且不会有两颗行星引力值相同。

    输出描述 Output Description

    仅包含一个正整数,表示完成比赛所需的最少时间。

    样例输入 Sample Input

    3 3
    1 100 100
    2 1 10
    1 3 1
    2 3 1

    样例输出 Sample Output

    12

    数据范围及提示 Data Size & Hint

    对于 30%的数据 N≤20,M≤50;
    对于 70%的数据 N≤200,M≤4000;
    对于100%的数据N≤800, M≤15000。输入数据中的任何数都不会超过10^6。

    这道题,个人看到双向边以后一般不会往网络流那个方向去考虑,因为网络流一般是单向边,但是不要忘了题目中已经红字标出那句话,这句话将双向边,转化为了单向边,

    编号大的无法到达编号小的点,这就十分好了,因为每个星球只能经过一次,所以裂点,经过这个星球的方式有两种,分别是通过能力爆发模式和高速航行模式来到达,这样

    建立一个S,和T,将每个点i裂成i和i+n两个节点。

    使S与所有i+n连一条边,边权为能力爆发转移到该星球的费用。

    然后使S与所有i连一条边,流量为1,因为每个星球只能经过一次,以此如果有边来到达其它星球。

    然后加入的双向通道,以u与v+n连边(u<v)边的花费为边权,然后流量为1。

    最后只需所有i+n与T连一条费用为0,流量为1的边即可,表示每个点最多只能为终点增加为1的流量。

    这类题目,十分巧妙,主要考虑不到如何建图,考虑到了以后,题目就十分明朗了,裸裸的跑一次什么网络流就好了。

      1 #include<cstdio>
      2 #include<algorithm>
      3 #include<cmath>
      4 #include<iostream>
      5 #include<cstring>
      6 #include<queue>
      7 using namespace std;
      8 
      9 const int INF=1e9+7,NN=807*2+7,MM=100007;
     10 
     11 int n,m,S,T;
     12 int cnt,head[NN],next[MM],rea[MM],val[MM],cost[MM];
     13 int dis[NN],flag[NN];
     14 struct Node
     15 {
     16     int e,fa;
     17     void init(){e=fa=-1;}
     18 }pre[NN];
     19 
     20 void add(int u,int v,int fee,int fare)
     21 {
     22     cnt++;
     23     next[cnt]=head[u];
     24     head[u]=cnt;
     25     rea[cnt]=v;
     26     val[cnt]=fee;
     27     cost[cnt]=fare;
     28 }
     29 bool Spfa()
     30 {
     31     for (int i=1;i<=T;i++)
     32     {
     33         flag[i]=0;
     34         dis[i]=INF;
     35         pre[i].init();
     36     }
     37     dis[S]=0,flag[S]=1;
     38     queue<int>q;
     39     while (!q.empty()) q.pop();
     40     q.push(S);
     41     while(!q.empty())
     42     {
     43         int u=q.front();
     44         q.pop();
     45         for (int i=head[u];i!=-1;i=next[i])
     46         {
     47             int v=rea[i],fee=cost[i];
     48             if ((dis[u]+fee<dis[v])&&val[i]>0)
     49             {
     50                 dis[v]=dis[u]+fee;
     51                 pre[v].fa=u,pre[v].e=i;
     52                 if (flag[v]==0)
     53                 {
     54                     flag[v]==1;
     55                     q.push(v);
     56                 }
     57             }
     58         }
     59         flag[u]=0;
     60     }
     61     if (dis[T]!=INF) return 1;
     62     else return 0;
     63 }
     64 void MFMC()
     65 {
     66     int Flow=0,Cost=0;
     67     while (Spfa())
     68     {
     69         int x=INF;
     70         for (int i=T;pre[i].fa!=-1;i=pre[i].fa)
     71         {
     72             int e=pre[i].e;
     73             x=min(x,val[e]);
     74         }
     75         Flow+=x,Cost+=x*dis[T];
     76         for (int i=T;pre[i].fa!=-1;i=pre[i].fa)
     77         {
     78             int e=pre[i].e;
     79             val[e]-=x,val[e^1]+=x;
     80         }
     81     }
     82     printf("%d
    ",Cost);
     83 }
     84 int main()
     85 {
     86     cnt=1;
     87     memset(head,-1,sizeof(head));
     88     scanf("%d%d",&n,&m);
     89     S=n*2+1,T=n*2+2;
     90     int x,y,z;
     91     for (int i=1;i<=n;i++)
     92     {
     93         scanf("%d",&x);
     94         add(S,i+n,1,x),add(i+n,S,0,-x);
     95         add(S,i,1,0),add(i,S,0,0);
     96         add(i+n,T,1,0),add(T,i+n,0,0);
     97     }
     98     for (int i=1;i<=m;i++)
     99     {
    100         scanf("%d%d%d",&x,&y,&z);
    101         if (x>y) swap(x,y);
    102         add(x,y+n,1,z),add(y+n,x,0,-z);
    103     }
    104     MFMC();
    105 }
  • 相关阅读:
    unittest生成html测试报告
    excel类封装
    023-linux(2)
    016-WebDriver API(2)
    015-WebDriver API
    014-unittest扩展
    013- unittest单元测试框架
    011-python列表,元组,字典的用法
    010-利用Selenium+python自动输入博客账号密码登录
    009-python一些问题整理
  • 原文地址:https://www.cnblogs.com/fengzhiyuan/p/7235834.html
Copyright © 2011-2022 走看看