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 }
  • 相关阅读:
    1026 Table Tennis (30)
    1029 Median
    1025 PAT Ranking (25)
    1017 Queueing at Bank (25)
    1014 Waiting in Line (30)
    1057 Stack (30)
    1010 Radix (25)
    1008 Elevator (20)
    字母大小写转换
    Nmap的基础知识
  • 原文地址:https://www.cnblogs.com/fengzhiyuan/p/7235834.html
Copyright © 2011-2022 走看看