• [SDOI2010] 星际竞速 (费用流)


    Source: SDOI2010 Round 1,Day 2,Problem 3.

     

    Description

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

    Input

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

    Output

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

    Sample Input

    starrace.in

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

    Sample Output

    starrace.out

    12

    HINT

    说明:先使用能力爆发模式到行星 1,花费时间 1。
    然后切换到高速航行模式,航行到行星 2,花费时间10。
    之后继续航行到行星 3完成比赛,花费时间 1。
    虽然看起来从行星 1到行星3再到行星 2更优,但我们却不能那样做,因为那会导致超能电驴爆炸。

    对于 30%的数据 N≤20,M≤50;
    对于 70%的数据 N≤200,M≤4000;
    对于100%的数据N≤800, M≤15000。输入数据中的任何数都不会超过10^6。
    输入数据保证任意两颗行星之间至多存在一条航道,且不会存在某颗行星到自己的航道。

    虽说是双向边,但是实际上还是单向的。

    将一个点拆成两个

    源点向每个点的入点连一条容量为1费用为0的边。

    源点向每个点的出点连一条容量为1费用为瞬移到该点所需时间的边。

    每个点的出点向汇点连一条容量为1费用为0的边。

    对于每条边(i,j),从i点入点向j点出点连一条容量为1费用为航路所需时间的边。

    然后跑费用流就好了

    PS:我在bzoj和cogs A了但是在洛谷被卡了一个点 只有90

      1 #include<queue>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<iostream>
      5 #define MAXN 150010
      6 
      7 using namespace std;
      8 
      9 const int N=810;
     10 const int INF=0x7fffffff;
     11 
     12 struct edge {
     13     int to;
     14     int next;
     15     int val;
     16     int fee;
     17 };
     18 edge w[MAXN];
     19 
     20 int head[MAXN],tot=1;
     21 
     22 int n,m,a,b,c,src,decc;
     23 
     24 int flow[N<<1],dis[N<<1],pre[N<<1];
     25 
     26 bool vis[N<<1];
     27 
     28 queue<int> Q;
     29 
     30 inline void read(int&x) {
     31     int f=1;x=0;char c=getchar();
     32     while(c>'9'||c<'0') {if(c=='-') f=-1;c=getchar();}
     33     while(c>='0'&&c<='9') {x=(x<<1)+(x<<3)+c-48;c=getchar();}
     34     x=x*f;
     35 }
     36 
     37 inline void add(int x,int y,int z,int f) {
     38     w[++tot].to=y;
     39     w[tot].fee=f;
     40     w[tot].val=z;
     41     w[tot].next=head[x];
     42     head[x]=tot;
     43 }
     44 
     45 inline void add_edge(int x,int y,int z,int f) {
     46     add(x,y,z,f);
     47     add(y,x,0,-f); 
     48 } 
     49 
     50 inline int change() {
     51     for(int i=pre[decc];i;i=pre[w[i^1].to]) {
     52         w[i].val-=flow[decc];
     53         w[i^1].val+=flow[decc];
     54     }
     55     return dis[decc]*flow[decc];
     56 }
     57 
     58 inline bool spfa() {
     59     for(int i=1;i<=n*2+1;i++) vis[i]=false,pre[i]=-1,dis[i]=flow[i]=INF;
     60     while(!Q.empty()) Q.pop();
     61     Q.push(src);
     62     dis[src]=0;
     63     vis[src]=true;
     64     pre[src]=0;
     65     while(!Q.empty()) {
     66         int u=Q.front();
     67         Q.pop();
     68         vis[u]=false;
     69         for(int i=head[u];i!=-1;i=w[i].next) {
     70             int to=w[i].to;
     71             if(dis[to]>dis[u]+w[i].fee&&w[i].val) {
     72                 dis[to]=dis[u]+w[i].fee;
     73                 flow[to]=min(flow[to],w[i].val);
     74                 pre[to]=i;
     75                 if(!vis[to]) {
     76                     Q.push(to);
     77                     vis[to]=true;
     78                 }
     79             }
     80         }
     81     }
     82     return dis[decc]!=INF;
     83 }
     84 
     85 inline int cost() {
     86     int ans=0;
     87     while(spfa()) 
     88       ans+=change();
     89     return ans;
     90 }
     91 
     92 inline int hhh() {
     93     read(n);read(m);
     94     src=0;decc=2*n+1;
     95     memset(head,-1,sizeof head);
     96     for(int i=1;i<=n;i++) {
     97         read(a);
     98         add_edge(src,i+n,1,a);
     99         add_edge(src,i,1,0);
    100         add_edge(i+n,decc,1,0);
    101     }
    102     for(int i=1;i<=m;i++) {
    103         read(a);read(b);read(c);
    104         if(a>b) swap(a,b);
    105         add_edge(a,b+n,1,c);
    106     }
    107     printf("%d
    ",cost());
    108     return 0;
    109 }
    110 
    111 int sb=hhh();
    112 int main() {;}
    代码


    作者:乌鸦坐飞机
    出处:http://www.cnblogs.com/whistle13326/
    新的风暴已经出现 怎么能够停止不前 穿越时空 竭尽全力 我会来到你身边 微笑面对危险 梦想成真不会遥远 鼓起勇气 坚定向前 奇迹一定会出现

     
  • 相关阅读:
    Apache与Nginx的优缺点比较
    [PHP基础]有关isset empty 函数的面试题
    PHP求解一个值是否为质数
    15个魔术方法的总结
    对象在类中的存储方式有哪些?
    cookie大小
    Tp3.2 和 Tp5.0之间的区别
    经典的面试题,(这是著名的约瑟夫环问题)
    怎么计算数据库有多大的数据量
    [置顶] 实用电子电路设计丛书
  • 原文地址:https://www.cnblogs.com/whistle13326/p/7339568.html
Copyright © 2020-2023  润新知