[ACM Day3] H.Legacy Code

本文介绍了一种通过图论方法来查找软件中未被使用的代码片段的技术。该技术首先通过哈希标识符找到所有主方法(PROGRAM),然后使用类似于洪水填充算法的广度优先搜索(BFS)来遍历所有可达的方法,最终找出那些从未被执行到的方法。

题目描述

Once again you lost days refactoring code, which never runs in the first place. Enough is enough – your time is better spent writing a tool that finds unused code!
Your software is divided into packages and executables. A package is a collection of meth- ods. Executables are packages defining among other methods exactly one method with name PROGRAM. This method is executed on the start of the corresponding executable. Ordinary packages have no method named PROGRAM.
Each method is uniquely identified by the combination of package and method names. E.g. the method with the identifier SuperGame::PROGRAM would be the main method of the executable SuperGame.
For every method in your software you are given a list of methods directly invoking it. Thus you can easily identify methods, that are never called from any method. However, your task is more challenging: you have to find unused methods. These are methods that are never reached by the control flow of any executable in your software.

数据范围

N<=400N<=400

分析

看着题目觉得很难,可能是一道神仙题,但是打完回去再看的时候发现其实很简单,对每个PROGAM直接hash一下,化成一道图论暴力就可以了,剩下的就是多源的一个类floodfill的东西,怕炸栈所以写了bfs。

#include <bits/stdc++.h>
#define rep( i , l , r ) for( int i = (l) ; i <= (r) ; ++i )
#define per( i , r , l ) for( int i = (r) ; i >= (l) ; --i )
#define erep( i , u ) for( int i = head[(u)] ; ~i ; i = e[i].nxt )
using namespace std;
int _read(){
    char ch = getchar();
    int x = 0 , f = 1 ;
    while( !isdigit( ch ) )
           if( ch == '-' ) f = -1 , ch = getchar();
           else ch = getchar();
    while( isdigit( ch ) )
           x = (ch  - '0') + x * 10 , ch =  getchar();
    return x * f;
}
const int maxn = 400 + 5 , maxm = 300000 + 5;
struct edge{
    int v , nxt;
} e[maxm];
int head[maxn] , _t = 0;
inline void addedge( int u , int v ){
    e[_t].v = v , e[_t].nxt = head[u] , head[u] = _t++;
}
const char S[10] = "::PROGRAM";
inline bool ck( string s ){
    if( s.length() <= 9 ) return 0;
    int l = s.length();
    rep( j , 0 , 8 )
        if( S[j] != s[l + j - 9] ) return 0;
    return 1;
}
map<string,int> h;
int f[maxn] , N , tot = 0;
void prework(){
    scanf("%d" , &N);
    rep( i , 1 , N ){
        string s; int K = 0;
        cin >> s >> K;
        if( h.count(s) == 0 ){
            h[s] = ++tot;
            f[tot] = ck( s );
        }
        rep( j , 1 , K ){
            string ss;
            cin >> ss;
            if( h.count(ss) == 0 ){
                h[ss] = ++tot;
                f[tot] = ck( ss ); 
            }
            addedge( h[ss] , h[s] );
        }
    }
}
#define FR front()
int dis[maxn];
void bfs(){
    queue<int> q;
    memset( dis , 0xff , sizeof dis );
    rep( i , 1 , tot )
        if( f[i] == 1 ){
            q.push( i ) ; dis[i] = 0;
        }
    while( !q.empty() ){
        int u = q.FR; q.pop();
        erep( i , u ){
            int v = e[i].v;
            if( dis[v] == -1 ){
                dis[v] = dis[u] + 1;
                q.push( v );
            }
        }
    }
}
inline int _max( int a , int b ){ return a > b ? a : b; }
int main(){
    memset( head , 0xff , sizeof head );
    prework();
    bfs();
    int ans = 0;
    rep( i , 1 , tot ) ans += ( dis[i] == -1 );
    cout << ans << endl;
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值