zoukankan      html  css  js  c++  java
  • POJ 3592 缩点+拓扑排序+最长路

    题目链接: http://poj.org/problem?id=3592

    题目大意:

      给定一个n*m的地图,有0-9表示某个格子上的value,‘*’表示该格子上有个时空门,可直接到指定的某个格子(可以自行选择是否使用时空门),‘#’表示该格子无法使用,某个格子的value只能被计算一次,问从起点(规定为左上角,我一直把northwest看成了右上角,伤不起)出发,每次只能往下走一格或往右走一格,最多能得到多大的value。

    分析:

      首先根据给定的关系建图,又因为有时空门的存在,所以必须缩点,

      对缩点后的图进行拓扑排序之后再dp,即可求得最长路。

    (PS: 这题我看了discuss,发现思路什么的对了,就是一点,起点我自己看成了右上角,伤不起啊~!~)

    代码(好像我的比较冗长的):

    poj3592
      1 /*3592    Accepted    428K    0MS    C++    4222B    2012-06-09 16:18:12*/
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <cmath>
      5 #include <iostream>
      6 #include <algorithm>
      7 #include <vector>
      8 using namespace std;
      9 
     10 #define mpair make_pair
     11 #define pii pair<int,int>
     12 #define MM(a,b) memset(a,b,sizeof(a));
     13 typedef long long lld;
     14 typedef unsigned long long u64;
     15 template<class T> bool up_max(T& a,const T& b){return b>a? a=b,1 : 0;}
     16 template<class T> bool up_min(T& a,const T& b){return b<a? a=b,1 : 0;}
     17 #define maxn 1640
     18 #define maxm 50
     19 
     20 int n,m,k, nv;
     21 int f[maxm][maxm];
     22 char ch[maxm][maxm];
     23 
     24 vector<int>g[maxn], adj[maxn];
     25 int mark[maxm][maxm];
     26 pii a[maxn], fp[maxn];
     27 
     28 void Read(){
     29     int i,j,x,y;
     30     scanf("%d %d\n", &n, &m);
     31     for(i=0;i<n;++i)
     32         for(j=0;j<m;++j){
     33             f[i][j]= i*m + j + 1;
     34             fp[i*m+j+1]= pii( i, j );
     35         }
     36     nv= n*m;
     37 
     38     k= 0;
     39     for(i=0;i<n;++i){
     40         for(j=0;j<m;++j){
     41             scanf("%c", &ch[i][j]);
     42             if( '*' == ch[i][j] )
     43                 mark[i][j]= ++k;
     44         }
     45         getchar();
     46     }
     47 
     48     for(i=1;i<=k;++i){
     49         scanf("%d%d", &x, &y);
     50         a[i]= pii( x, y );
     51     }
     52 }
     53 
     54 void build_graph(){
     55     int i,j;
     56     for(i=1;i<=nv;++i) g[i].clear();
     57     for(i=0;i<n;++i){
     58         for(j=0;j<m;++j){
     59             if( '#' == ch[i][j] ) continue;
     60 
     61             if( i+1<n && '#'!=ch[i+1][j] ){ /// go down;
     62                 g[ f[i][j] ].push_back( f[i+1][j] );
     63             }
     64             if( j+1<m && '#'!=ch[i][j+1] ){ /// go left;
     65                 g[ f[i][j] ].push_back( f[i][j+1] );
     66             }
     67             if( '*' == ch[i][j] ){ /// can use magic power;
     68                 int t= mark[i][j];
     69                 int x= a[t].first, y= a[t].second;
     70                 if( '#' != ch[x][y] ) ///
     71                     g[ f[i][j] ].push_back( f[x][y] );
     72             }
     73         }
     74     }
     75 }
     76 
     77 int c[maxn]; /// each block's sum-value;
     78 
     79 int Bcnt, Index, Top;
     80 int low[maxn], dfn[maxn], stack[maxn], belong[maxn];
     81 bool inq[maxn];
     82 void Init_tarjan(){
     83     Bcnt= Index= Top= 0;
     84     for(int i=1;i<=nv;++i) low[i]= dfn[i]= inq[i]= 0;
     85 }
     86 void Tarjan(int u){
     87     stack[++Top]= u;
     88     inq[u]= 1;
     89     low[u]= dfn[u]= ++Index;
     90     for(int i=0;i<g[u].size();++i){
     91         int v= g[u][i];
     92         if( !dfn[v] ){
     93             Tarjan( v );
     94             up_min( low[u], low[v] );
     95         }
     96         else if( inq[v] )
     97             up_min( low[u], dfn[v] );
     98     }
     99     if( low[u]==dfn[u] ){
    100         ++Bcnt;
    101         int v;
    102         do{
    103             v= stack[Top--];
    104             inq[v]= 0;
    105             belong[v]= Bcnt;
    106             int x= fp[v].first, y= fp[v].second;
    107             if( '1'<=ch[x][y] && ch[x][y]<='9' )
    108                 c[Bcnt]+= ch[x][y]-'0';
    109         }while(u!=v);
    110     }
    111 }
    112 
    113 int in[maxn];
    114 void build2(int u){
    115     inq[u]= 1;
    116     for(int i=0;i<g[u].size();++i){
    117         int v= g[u][i];
    118         if( belong[v] != belong[u] ){
    119             adj[ belong[u] ].push_back( belong[v] );
    120             ++in[ belong[v] ];
    121         }
    122         if( !inq[v] ) build2(v); /// here!!!!!!!!!!!!!!!!!!!;
    123     }
    124 }
    125 
    126 int *que; ///
    127 int dp[maxn];
    128 int Topsort(){
    129     int i,head=0,tail=0;
    130     fill( dp, dp+1+Bcnt, 0 );
    131     /// for(i=1;i<=Bcnt;++i) if( in[i]==0 ) { que[tail++]= i; dp[i]= c[i]; }
    132     que[tail++]= belong[1]; ///!!!!!!!!!!!!!
    133     dp[belong[1]]= c[belong[1]];
    134 
    135     while( head<tail ){
    136         int u= que[head++];
    137         for(int i=0;i<adj[u].size();++i){
    138             int v= adj[u][i];
    139             if( --in[v] == 0 )
    140                 que[tail++]= v;
    141         }
    142     }
    143 
    144     for(i=0;i<tail;++i){
    145         int u= que[i];
    146         for(int j=0;j<adj[u].size();++j){
    147             int v= adj[u][j];
    148             up_max( dp[v], dp[u]+c[v] );
    149         }
    150     }
    151 
    152     int ans= 0;
    153     for(i=0;i<tail;++i) up_max( ans, dp[ que[i] ] ); /// que[i];
    154     return ans;
    155 }
    156 
    157 int solve(){
    158     build_graph();
    159     Init_tarjan();
    160     fill( c, c+nv+1, 0 );
    161     Tarjan(1); ///
    162 
    163     for(int i=1;i<=Bcnt;++i) adj[i].clear(), inq[i]= 0, in[i]= 0;
    164     build2(1);
    165 
    166     que= stack;
    167     return Topsort();
    168 }
    169 
    170 int main()
    171 {
    172     //freopen("poj3592.in","r",stdin);
    173     int T;
    174     cin>>T;
    175     while(T--){
    176         Read();
    177         cout<< solve() <<endl;
    178     }
    179 }
  • 相关阅读:
    一些关于视频相关基础概念
    熟悉某项目代码---零碎小知识总结
    C#中如何判断一个字符是汉字
    面试碰到一个这样的题------ 输入为一个字符串和字节数,输出为按字节截取的字符串
    C# 拼Json格式字符串 返回前段js 出错解决
    学习maple
    格林公式
    麦克斯韦方程组 (Maxwell's equation)的简单解释
    关于Ciarlet的泛函的一道homework的一个想法
    关于分开编写多个LaTeX文件的一点微小的总结
  • 原文地址:https://www.cnblogs.com/yimao/p/2543286.html
Copyright © 2011-2022 走看看