• BZOJ 2324: [ZJOI2011]营救皮卡丘


    2324: [ZJOI2011]营救皮卡丘

    Time Limit: 10 Sec  Memory Limit: 256 MB
    Submit: 2340  Solved: 963
    [Submit][Status][Discuss]

    Description

    皮卡丘被火箭队用邪恶的计谋抢走了!这三个坏家伙还给小智留下了赤果果的挑衅!为了皮卡丘,也为了正义,小智和他的朋友们义不容辞的踏上了营救皮卡丘的道路。

    火箭队一共有N个据点,据点之间存在M条双向道路。据点分别从1N标号。小智一行K人从真新镇出发,营救被困在N号据点的皮卡丘。为了方便起见,我们将真新镇视为0号据点,一开始K个人都在0号点。

    由于火箭队的重重布防,要想摧毁K号据点,必须按照顺序先摧毁1K-1号据点,并且,如果K-1号据点没有被摧毁,由于防御的连锁性,小智一行任何一个人进入据点K,都会被发现,并产生严重后果。因此,在K-1号据点被摧毁之前,任何人是不能够经过K号据点的。

    为了简化问题,我们忽略战斗环节,小智一行任何一个人经过K号据点即认为K号据点被摧毁。被摧毁的据点依然是可以被经过的。

    K个人是可以分头行动的,只要有任何一个人在K-1号据点被摧毁之后,经过K号据点,K号据点就被摧毁了。显然的,只要N号据点被摧毁,皮卡丘就得救了。

    野外的道路是不安全的,因此小智一行希望在摧毁N号据点救出皮卡丘的同时,使得K个人所经过的道路的长度总和最少。

    请你帮助小智设计一个最佳的营救方案吧!

     

    Input

    第一行包含三个正整数N,M,K。表示一共有N+1个据点,分别从0N编号,以及M条无向边。一开始小智一行共K个人均位于0号点。 

    接下来M行,每行三个非负整数,第i行的整数为Ai,Bi,Li。表示存在一条从Ai号据点到Bi号据点的长度为Li的道路。

    Output

    仅包含一个整数S,为营救皮卡丘所需要经过的最小的道路总和。

    Sample Input

    3 4 2
    0 1 1
    1 2 1
    2 3 100
    0 3 1

    Sample Output

    3
    【样例说明】
    小智和小霞一起前去营救皮卡丘。在最优方案中,小智先从真新镇前往1号点,接着前往2号据点。当小智成功摧毁2号据点之后,小霞从真新镇出发直接前往3号据点,救出皮卡丘。

    HINT

    对于100%的数据满足N ≤ 150, M ≤ 20 000, 1 ≤ K ≤ 10, Li ≤ 10 000, 保证小智一行一定能够救出皮卡丘。至于为什么K ≤ 10,你可以认为最终在小智的号召下,小智,小霞,小刚,小建,小遥,小胜,小光,艾莉丝,天桐,还有去日本旅游的黑猫警长,一同前去大战火箭队。

    Source

    [Submit][Status][Discuss]

    把字体调成华文新魏,一群小伙伴都看成了常数皮卡丘,2333。

    修改后的Floyd预处理每个点对之间的距离,建图跑最小费用最大流,然而蒟蒻的我并不会做,感谢 @NeighThorn 大佬的指导。

      1 #include <cstdio>
      2 #include <cstring>
      3  
      4 template <class T>
      5 __inline T max(const T &a, const T &b)
      6 {
      7     return a > b ? a : b;
      8 }
      9  
     10 template <class T>
     11 __inline T min(const T &a, const T &b)
     12 {
     13     return a < b ? a : b;
     14 }
     15  
     16 __inline char nextChar(void)
     17 {
     18     static const int siz = 1 << 20;
     19      
     20     static char buf[siz];
     21     static char *hd = buf + siz;
     22     static char *tl = buf + siz;
     23      
     24     if (hd == tl)
     25         fread(hd = buf, 1, siz, stdin);
     26      
     27     return *hd++;
     28 }
     29  
     30 __inline int nextInt(void)
     31 {
     32     register int ret = 0;
     33     register bool neg = false;
     34     register char bit = nextChar();
     35      
     36     for (; bit < 48; bit = nextChar())
     37         if (bit == '-')neg = !neg;
     38      
     39     for (; bit > 47; bit = nextChar())
     40         ret = ret * 10 + bit - 48;
     41      
     42     return neg ? -ret : ret;
     43 }
     44  
     45 const int inf = 2e9;
     46 const int mxn = 155;
     47 const int mxm = 1000005;
     48  
     49 int n, m, q;
     50  
     51 int G[mxn][mxn];
     52  
     53 inline void readGraph(void)
     54 {
     55     for (int i = 0; i <= n; ++i)
     56         for (int j = 0; j <= n; ++j)
     57             G[i][j] = i == j ? 0 : inf;
     58      
     59     for (int i = 1; i <= m; ++i)
     60     {
     61         int x = nextInt();
     62         int y = nextInt();
     63         int w = nextInt();
     64          
     65         G[x][y] = min(G[x][y], w);
     66         G[y][x] = min(G[y][x], w);
     67     }
     68 }
     69  
     70 inline void preworkFloyd(void)
     71 {
     72     for (int k = 0; k <= n; ++k)
     73         for (int i = 0; i <= n; ++i)if (G[i][k] < inf)
     74             for (int j = 0; j <= n; ++j)if (G[k][j] < inf)
     75                 if (k < i || k < j)G[i][j] = min(G[i][j], G[i][k] + G[k][j]);
     76 }
     77  
     78 int s, t, p;
     79 int hd[mxm];
     80 int nt[mxm];
     81 int to[mxm];
     82 int fl[mxm];
     83 int vl[mxm];
     84  
     85 inline void addEdge(int u, int v, int f, int w)
     86 {
     87     static int tot = 0;
     88      
     89     nt[tot] = hd[u], to[tot] = v, fl[tot] = f, vl[tot] = +w, hd[u] = tot++;
     90     nt[tot] = hd[v], to[tot] = u, fl[tot] = 0, vl[tot] = -w, hd[v] = tot++;
     91 }
     92  
     93 int dis[mxm];
     94 int pre[mxm];
     95  
     96 inline bool spfa(void)
     97 {
     98     static int que[mxm];
     99     static int inq[mxm];
    100     static int head, tail;
    101      
    102     for (int i = s; i <= t; ++i)
    103         dis[i] = inf, inq[i] = 0;
    104      
    105     dis[que[head = 0] = s] = 0, tail = 1, pre[s] = -1;
    106      
    107     while (head != tail)
    108     {
    109         int u = que[head++], v; inq[u] = 0;
    110          
    111         for (int i = hd[u]; ~i; i = nt[i])
    112             if (fl[i] && dis[v = to[i]] > dis[u] + vl[i])
    113             {
    114                 pre[v] = i ^ 1;
    115                 dis[v] = dis[u] + vl[i];
    116                  
    117                 if (!inq[v])
    118                     inq[que[tail++] = v] = 1;
    119             }
    120     }
    121      
    122     return dis[t] < inf;
    123 }
    124  
    125 inline int minCost(void)
    126 {
    127     int cost = 0;
    128      
    129     while (spfa())
    130     {
    131         int flow = inf;
    132          
    133         for (int i = pre[t]; ~i; i = pre[to[i]])
    134             flow = min(flow, fl[i ^ 1]);
    135          
    136         for (int i = pre[t]; ~i; i = pre[to[i]])
    137             fl[i] += flow, fl[i ^ 1] -= flow;
    138          
    139         cost += dis[t] * flow;
    140     }
    141      
    142     return cost;
    143 }
    144  
    145 inline void buildNetwork(void)
    146 {
    147     memset(hd, -1, sizeof(hd));
    148      
    149     s = 0;
    150     p = 2*n + 1;
    151     t = 2*n + 2;
    152      
    153     addEdge(s, p, q, 0);
    154      
    155     for (int i = 1; i <= n; ++i)
    156         addEdge(s, i, 1, 0), 
    157         addEdge(i + n, i, 1, 0),
    158         addEdge(i + n, t, 1, 0),
    159         addEdge(p, i + n, 1, G[0][i]);
    160      
    161     for (int i = 1; i <= n; ++i)
    162         for (int j = i + 1; j <= n; ++j)
    163             addEdge(i, j + n, 1, G[i][j]); 
    164 }
    165  
    166 signed main(void)
    167 {
    168     n = nextInt();
    169     m = nextInt();
    170     q = nextInt();
    171      
    172     readGraph();
    173      
    174     preworkFloyd();
    175      
    176     buildNetwork();
    177      
    178     printf("%d
    ", minCost());
    179 }

    @Author: YouSiki

  • 相关阅读:
    PHP array_intersect_uassoc
    PHP array_intersect_key
    PHP array_intersect_assoc
    PHP array_flip
    PHP array_filter
    PHP array_fill
    PHP array_fill_keys
    Android4.0-Fragment框架实现方式剖析
    Fragment 生命周期
    WebView
  • 原文地址:https://www.cnblogs.com/yousiki/p/6347732.html
Copyright © 2020-2023  润新知