zoukankan      html  css  js  c++  java
  • bzoj 1927 [Sdoi2010]星际竞速(最小费用最大流)

    1927: [Sdoi2010]星际竞速

    Time Limit: 20 Sec  Memory Limit: 259 MB
    Submit: 1576  Solved: 954
    [Submit][Status][Discuss]

    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

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

    Sample Output

    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。输入数据中的任何数都不会超过106

    输入数据保证任意两颗行星之间至多存在一条航道,且不会存在某颗行星到
    自己的航道。

    Source

    【思路】

           最小费用最大流。

           构图:拆点Xi,Yi。连边(S,Xi,1,0)(Yi,T,1,0),如果i和j有长度为w的边则连(Xi,Yj,1,w)。注意对于”能量爆发”而言并不需要每对点之间连边,到每个点的瞬移时间是固定的,如果值为w只需要连边(S,Yi,1,w)即可,相当于能量爆发与高速行驶之间的最优抉择。

    【代码】

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<queue>
      4 #include<vector>
      5 #define FOR(a,b,c) for(int a=(b);a<(c);a++)
      6 using namespace std;
      7 
      8 typedef long long LL;
      9 const int maxn = 2000+10;
     10 const int INF = 1e9;
     11 
     12 struct Edge { int u,v,cap,flow,cost;
     13 };
     14 struct zkw {
     15     int n,m,s,t;
     16     int d[maxn],vis[maxn];
     17     vector<Edge> es;
     18     vector<int> G[maxn];
     19     
     20     void init(int n) {
     21         this->n=n;
     22         es.clear();
     23         for(int i=0;i<n;i++) G[i].clear();
     24     }
     25     void AddEdge(int u,int v,int cap,int cost) {
     26         es.push_back((Edge){u,v,cap,0,cost});
     27         es.push_back((Edge){v,u,0,0,-cost});
     28         int m=es.size();
     29         G[u].push_back(m-2) , G[v].push_back(m-1);
     30     }
     31     bool spfa() {
     32         memset(vis,0,sizeof(vis));
     33         for(int i=0;i<n;i++) d[i]=INF;
     34         queue<int> q;
     35         d[t]=0 , vis[t]=1 , q.push(t);
     36         while(!q.empty()) {
     37             int u=q.front(); q.pop() , vis[u]=0;
     38             for(int i=0;i<G[u].size();i++) {
     39                 Edge& e=es[G[u][i]];
     40                 int v=e.v;
     41                 if(es[G[u][i]^1].cap && d[v]>d[u]-e.cost) {
     42                     d[v]=d[u]-e.cost;
     43                     if(!vis[v]) {
     44                         vis[v]=1; q.push(v);
     45                     }
     46                 }
     47             }
     48         }
     49         return d[s]!=INF;
     50     }
     51     int dfs(int u,int a,LL& cost) {
     52         vis[u]=1; if(u==t) return a;
     53         int used=0,w;
     54         for(int i=0;i<G[u].size();i++) {
     55             Edge& e=es[G[u][i]];
     56             int v=e.v;
     57             if(d[v]==d[u]-e.cost && e.cap && !vis[v]) {
     58                 w=dfs(v,min(a-used,e.cap),cost);
     59                 e.cap-=w , es[G[u][i]^1].cap+=w;
     60                 cost+=w*e.cost;
     61                 used+=w; if(used==a) return a;
     62             }
     63         }
     64         return used;
     65     }
     66     int Mincost(int s,int t,LL& cost) {
     67         this->s=s , this->t=t;
     68         int flow=0; cost=0;
     69         while(spfa()) {
     70             vis[t]=1;
     71             while(vis[t]) {
     72                 memset(vis,0,sizeof(vis));
     73                 flow+=dfs(s,INF,cost);
     74             }
     75         }
     76         return flow;
     77     }
     78 } mc;
     79 
     80 int n,m;
     81 
     82 int main() {
     83     scanf("%d%d",&n,&m);
     84     mc.init(n+n+2);
     85     int s=n+n,t=s+1,u,v,w;
     86     FOR(i,0,n) {
     87         scanf("%d",&w);
     88         mc.AddEdge(s,i,1,0);
     89         mc.AddEdge(i+n,t,1,0);
     90         mc.AddEdge(s,i+n,1,w);
     91     }
     92     FOR(i,0,m) {
     93         scanf("%d%d%d",&u,&v,&w);
     94         u--,v--; if(v<u) swap(u,v);
     95         mc.AddEdge(u,v+n,1,w);
     96     }
     97     LL cost;
     98     mc.Mincost(s,t,cost);
     99     printf("%lld",cost);
    100     return 0;
    101 }
  • 相关阅读:
    js对象数组(JSON) 根据某个共同字段 分组
    一个 函数 用来转化esSearch 的range 条件
    关于 vuex 报错 Do not mutate vuex store state outside mutation handlers.
    android listview 重用view导致的选择混乱问题
    android SDK和ADT的更新
    Android中adb push和adb install的使用区别
    pycharm中添加扩展工具pylint
    su Authentication failure解决
    Putty以及adb网络调试
    有关android源码编译的几个问题
  • 原文地址:https://www.cnblogs.com/lidaxin/p/5094271.html
Copyright © 2011-2022 走看看