• uvalive 3661 Animal Run


    题意:

    一群动物想从动物园逃离,从一个图的左上角出发,只有到达右下角才能彻底逃离。

    动物园的管理者为了防止他们逃跑,安排了若干人在路上防守。

    现在问最少需要花多少人能够封锁动物逃跑的路线。

    思路:

    简单画一画知道,就是找一个边的集合把整个图分成两个部分,且要求这些边的权值最小,这是著名的最小割问题(虽然我没有学过。

    不过可以用最短路解决。

    经过尝试可以知道,从下到上的连线,从左到右的连线,从左到上的连线以及从下到右的连线均可以到达目的,其它的就不行,比如从下到左。

    所以,可以以每一条边作为一个点,把左边界的边和下边界的边作为起点,右边界和上边界作为终点,求出最短路即是答案。

    接下来就是连边的问题,如果i和j之间连边,那么从i连向j,那么这条边的权值就是i边的权值(这时候是把边当作点的);若是从j向i连边,那么就是j边的权值作为这条边的权值。

    最后是哪些些边之间要连边的问题,处在同一个小三角形当中的边两两之间都要连边。

    一开始以为只有对角线要和两条直角边连线,最后画图发现其实两条直角边互相连线也是必须的。

    如图:(自己画的,很丑)

    这题用到了超级源点的技巧,然后优先队列优化的Dijkstra。

    最难的还是如何给边编号的问题,我所用的编号就是题目的输入顺序,水平边和竖直边以及对角线的编号之间存在着一定的关系,可以推导得出,只不过比较繁琐,所以代码略长。

    代码:

      1 #include <stdio.h>
      2 #include <string.h>
      3 #include <algorithm>
      4 #include <vector>
      5 #include <queue>
      6 using namespace std;
      7 
      8 const int N = 5e6;
      9 const int inf = 0x3f3f3f3f;
     10 
     11 typedef pair<int,int> pii;
     12 
     13 int d[N];
     14 int w[N];
     15 
     16 struct edge
     17 {
     18     int to,cost;
     19     edge(){};
     20     edge(int a,int b)
     21     {
     22         to = a;
     23         cost = b;
     24     }
     25 };
     26 
     27 vector<edge> es;
     28 vector<int> g[N];
     29 
     30 void adde(int from,int to,int cost)
     31 {
     32     es.push_back(edge(to,cost));
     33     g[from].push_back(es.size() - 1);
     34 }
     35 
     36 void init(int n)
     37 {
     38     es.clear();
     39     
     40     for (int i = 0;i <= n;i++) g[i].clear();
     41     
     42     memset(d,inf,sizeof(d));
     43 }
     44 
     45 void dij(int n)
     46 {
     47     priority_queue<pii,vector<pii>,greater<pii> > pq;
     48     
     49     d[0] = 0;
     50     
     51     pq.push(pii(0,0));
     52     
     53     while (!pq.empty())
     54     {
     55         pii x = pq.top();pq.pop();
     56         
     57         int v = x.second;
     58         
     59         if (d[v] < x.first) continue;
     60         
     61         for (int i = 0;i < g[v].size();i++)
     62         {
     63             int id = g[v][i];
     64             
     65             edge e = es[id];
     66             
     67             if (d[e.to] > e.cost + d[v])
     68             {
     69                 d[e.to] = d[v] + e.cost;
     70                 pq.push(pii(d[e.to],e.to));
     71             }
     72         } 
     73     }
     74 }
     75 
     76 int main()
     77 {
     78     int n,m;
     79     int kase = 0;
     80     
     81     while (scanf("%d%d",&n,&m) != EOF)
     82     {
     83         if (m == 0 && n == 0) break;
     84         
     85         int cnt = 0;
     86         
     87         //init(n,m);
     88         
     89         for (int i = 0;i < n;i++)
     90         {
     91             for (int j = 0;j < m - 1;j++)
     92             {
     93                 int tmp;
     94                 
     95                 scanf("%d",&tmp);
     96                 
     97                 w[++cnt] = tmp;
     98             }
     99         }
    100         
    101         for (int i = 0;i < n - 1;i++)
    102         {
    103             for (int j = 0;j < m;j++)
    104             {
    105                 int tmp;
    106                 scanf("%d",&tmp);
    107                 w[++cnt] = tmp;
    108             }
    109         }
    110         
    111         for (int i = 0;i < n - 1;i++)
    112         {
    113             for (int j = 0;j < m - 1;j++)
    114             {
    115                 int tmp;
    116                 scanf("%d",&tmp);
    117                 w[++cnt] = tmp;
    118             }
    119         }
    120         
    121         int rs = 1,cs = n * (m - 1) + 1,ds = n * (m - 1) + m * (n - 1) + 1;
    122         
    123         //int sume = n * (m - 1) + m * (n - 1) + (m - 1) * (n - 1);
    124         
    125         init(cnt);
    126         
    127         for (int i = ds;i <= cnt;i++)
    128         {
    129             int num = (i - ds) / (m - 1);
    130             int curds = ds + (m - 1) * num;
    131             int curcs = cs + num * m;
    132             int currs = rs + num * (m - 1);
    133             int tmp = i - curds;
    134             int curc = curcs + tmp,curr = currs + tmp;
    135             
    136             adde(curc,i,w[curc]);
    137             adde(i,curc,w[i]);
    138             adde(i,curc + 1,w[i]);
    139             adde(curc+1,i,w[curc+1]);
    140             adde(i,curr,w[i]);
    141             adde(curr,i,w[curr]);
    142             adde(curr + m - 1,i,w[curr + m - 1]);
    143             adde(i,curr + m - 1,w[i]);
    144             adde(curc,curr+m-1,w[curc]);
    145             adde(curr + m - 1,curc,w[curr + m - 1]);
    146             adde(curr,curc + 1,w[curr]);
    147             adde(curc+1,curr,w[curc+1]);
    148         }
    149         
    150         for (int i = 0;i < n - 1;i++)
    151         {
    152             adde(0,cs + i * m,0);
    153         }
    154         
    155         for (int i = 0;i < m - 1;i++)
    156         {
    157             adde(0,(n - 1) * (m - 1) + 1 + i,0);
    158         }
    159         
    160         dij(cnt);
    161         
    162         int ans = inf;
    163         
    164         for (int i = 1;i <= m - 1;i++)
    165         {
    166             ans = min(ans,d[i] + w[i]);
    167         }
    168         
    169         for (int i = 1;i <= n - 1;i++)
    170         {
    171             int v = n * (m - 1) + m * i;
    172             ans = min(ans,d[v] + w[v]);
    173         }
    174         
    175         printf("Case %d: Minimum = %d
    ",++kase,ans);
    176     }
    177     
    178     return 0;
    179 }
  • 相关阅读:
    Alpha冲刺第一天
    团队项目-需求分析
    设计模式第二次作业
    设计模式第一次作业
    冲刺合集
    冲刺NO.12
    项目测试
    冲刺NO.11
    冲刺NO.9
    冲刺NO.10
  • 原文地址:https://www.cnblogs.com/kickit/p/8809255.html
Copyright © 2020-2023  润新知