zoukankan      html  css  js  c++  java
  • POJ3160 Father Christmas flymouse 圣诞老人给集训队送礼物

    /*
    *State: POJ3160 Accepted    1812K    63MS    C++    3743B    
    *题目大意:
    *        一个圣诞老人去给n个同学送东西,然后每个同学会给圣诞老人评价(可正负),
    *        然后n个同学的地址是一个有向有环图,每到一个同学家门口,圣诞老人可以
    *        选择进去,或者不进去,圣诞老人走到无路可走为止,然后要求给圣诞老人选
    *        一个起点,使得圣诞老人这次旅行获得的权值最大。
    *解题思路:
    *        题意看了好久啊,有向有环图,还可以选择拿权值或者不拿,最终要求总共最
    *        大权值,那么可以一开始就给点赋权值,如果权值为负就赋值为0,然后给有向
    *        有环图缩点。之后再把缩点后的图入度为0的点都用一个虚拟节点汇点,然后从
    *        这个虚拟节点开始用spfa求最长路,最后算一下出度为0的点的最长度的最大值
    *        即为所求。
    *解题感想:
    *        其实题目还是挺基础的,只是代码比较长,足足写了200+ rows,然后一开始用
    *        树形dp去计算最大值,后来wa了一次画图发现,这样行不通,因为缩点后的图
    *        是DAG而不是树形,DAG有可能点是公用的,所以用类似记忆化搜索的树形dp是
    *        不行的,相反,转化为最长路却很容易算出答案。
    *        最后还是wa了三次,re了一次,re是因为一开始用了向量去存邻接表,发现速度
    *        慢得很,就索性改为静态邻接表,有一个地方看错了,不过还好,re很快就查了
    *        出来,剩下的wa就够蛋疼的了,一开始是发现初始化少了一些,然后很冲动地
    *        交,结果还是wa,后来蛋疼无比之时,发现,汗死我了,我怎么把最长路写成了
    *        最短路,我是不是最短路写疯了?一写spfa就写成了最短路,汗死我~~~~~~~~~
    *        思维定势的痛楚。不过还是那样,200+的代码,一定要wa一次,很少能1a,但是
    *        花点儿时间认真查,还是可以查出来的。
    */
    View Code
      1 #include <iostream>
      2 #include <queue>
      3 using namespace std;
      4 
      5 const int MAXN = 30005;
      6 const int MAXE = 150005;
      7 const int inf = 0x3f3f3f3f;
      8 
      9 typedef struct _edge
     10 {
     11     int v, next;
     12 }E;
     13 E edge[MAXE];
     14 int cntEdge, head[MAXN];
     15 int myS[MAXN], top;
     16 int weight[MAXN], dfn[MAXN], low[MAXN], step;
     17 int inS[MAXN], scc, id[MAXN];
     18 
     19 //缩点,建DAG
     20 typedef struct _node
     21 {
     22     int v, w, next;
     23 }N;
     24 N sccEdge[MAXE];
     25 int sccHead[MAXN], sccCntEdge;
     26 int idw[MAXN], in[MAXN], out[MAXN];
     27 
     28 void init()
     29 {
     30     top = 0;
     31     step = cntEdge = sccCntEdge = 0;
     32     scc = 1;
     33     for(int i = 0; i < MAXN; i++)
     34     {
     35         myS[i] = 0;
     36         in[i] = out[i] = 0;
     37         weight[i] = 0;
     38         id[i] = -1;
     39         sccHead[i] = head[i] = -1;
     40         inS[i] = idw[i] = 0;
     41         dfn[i] = low[i] = -1;
     42     }
     43 }
     44 
     45 void addEdge(int u, int v)
     46 {
     47     edge[cntEdge].v = v;
     48     edge[cntEdge].next = head[u];
     49     head[u] = cntEdge++;
     50 }
     51 
     52 void tarjan_scc(int n)
     53 {
     54     dfn[n] = low[n] = ++step;
     55     myS[top++] = n;
     56     inS[n] = 1;
     57     for(int f = head[n]; f != -1; f = edge[f].next)
     58     {
     59         int son = edge[f].v;
     60         if(dfn[son] == -1)
     61         {
     62             tarjan_scc(son);
     63             low[n] = min(low[n], low[son]);
     64         }
     65         else if(inS[son] == 1)
     66             low[n] = min(low[n], dfn[son]);
     67     }
     68 
     69     if(low[n] == dfn[n] && top != 0)
     70     {
     71         int tmp;
     72         do
     73         {
     74             tmp = myS[--top];
     75 
     76             inS[tmp] = 0;
     77             id[tmp] = scc;
     78             idw[scc] += weight[tmp];
     79             
     80         }while(top != 0 && tmp != n);
     81         scc++;
     82     }
     83 }
     84 
     85 int spfa(int s)
     86 {
     87     int dis[MAXN], inQ[MAXN] = {0};
     88     for(int i = 0; i < MAXN; i++)
     89         dis[i] = -inf;
     90     queue<int> Q;
     91 
     92     Q.push(s);
     93     dis[s] = 0;
     94     inQ[s] = 1;
     95 
     96     while(!Q.empty())
     97     {
     98         int pre = Q.front();
     99         Q.pop();
    100         inQ[pre] = 0;
    101 
    102         for(int i = sccHead[pre]; i != -1; i = sccEdge[i].next)
    103         {
    104             int son = sccEdge[i].v, w = sccEdge[i].w;
    105             if(dis[son] < dis[pre] + w)
    106             {
    107                 dis[son] = dis[pre] + w;
    108                 if(inQ[son] == 0)
    109                 {
    110                     Q.push(son);
    111                     inQ[son] = 1;
    112                 }
    113             }
    114         }
    115     }
    116 
    117     int Max = 0;
    118     for(int i = 1; i < scc; i++)
    119     {
    120         if(out[i] == 0)
    121         {
    122             if(dis[i] > Max)
    123                 Max = dis[i];
    124         }
    125     }
    126     return Max;
    127 }
    128 
    129 void bulid_scc(int n, int &sol)
    130 {
    131     int u, v;
    132     for(int i = 0; i < n; i++)
    133     {
    134         for(int j = head[i]; j != -1; j = edge[j].next)
    135         {
    136             u = i, v = edge[j].v;
    137             if(id[u] == id[v])
    138                 continue;
    139             else
    140             {
    141                 sccEdge[sccCntEdge].v = id[v];
    142                 sccEdge[sccCntEdge].w = idw[id[v]];
    143                 sccEdge[sccCntEdge].next = sccHead[id[u]];
    144                 sccHead[id[u]] = sccCntEdge++;
    145 
    146                 in[id[v]]++;
    147                 out[id[u]]++;
    148             }
    149         }
    150     }
    151 
    152     int Max = 0;
    153     for(int i = 1; i < scc; i++)
    154     {
    155         if(in[i] == 0)
    156         {
    157             sccEdge[sccCntEdge].v = i;
    158             sccEdge[sccCntEdge].w = idw[i];
    159             sccEdge[sccCntEdge].next = sccHead[0];
    160             sccHead[0] = sccCntEdge++;
    161 
    162         }
    163     }
    164 
    165     sol = spfa(0);
    166     return ;
    167 }
    168 
    169 int main(void)
    170 {
    171 #ifndef ONLINE_JUDGE
    172     freopen("in.txt", "r", stdin);
    173 #endif
    174 
    175     int n, m;
    176     while(scanf("%d %d", &n, &m) == 2)
    177     {
    178         int u, v, t;
    179         init();
    180         for(int i = 0; i < n; i++)
    181         {
    182             scanf("%d", &t);
    183             if(t > 0)
    184                 weight[i] = t;
    185             else
    186                 weight[i] = 0;
    187         }
    188         for(int i = 0; i < m; i++)
    189         {
    190             scanf("%d %d", &u, &v);
    191             addEdge(u, v);
    192         }
    193         for(int i = 0; i < n; i++)
    194         {
    195             if(dfn[i] == -1)
    196                 tarjan_scc(i);
    197         }
    198         int sol;
    199         bulid_scc(n, sol);
    200         printf("%d\n", sol);
    201     }
    202     return 0;
    203 }
  • 相关阅读:
    ZJOI2006 物流运输
    codevs 1403 新三国争霸
    (一) MySQL学习笔记:MySQL安装图解
    多线程同步
    SendMessage和PostMessage区别
    VS2008 MFC 配置 Gdiplus
    IE7常用的几个快捷键 你常用的是哪个
    匆匆的六年 收获了什么
    python 代码题07 sorted函数
    python 代码题06 回数是指从左向右读和从右向左读都是一样的数,例如12321,909。请利用filter()筛选出回数
  • 原文地址:https://www.cnblogs.com/cchun/p/2641126.html
Copyright © 2011-2022 走看看