zoukankan      html  css  js  c++  java
  • HDU 4014 Jimmy’s travel plan(图计数)

    Jimmy’s travel plan

    Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65768/65768 K (Java/Others)
    Total Submission(s): 341    Accepted Submission(s): 58


    Problem Description
    Jimmy lives in a huge kingdom which contains lots of beautiful cities. He also loves traveling very much, and even would like to visit each city in the country. Jaddy, his secretary, is now helping him to plan the routes, however, Jaddy suddenly find that is quite a tough task because it is possible for Jimmy to ask route’s information toward any city. What was worth? Jaddy has to response for queries about the distance information nearly between any pair of cities due to the undeterminable starting city which Jimmy is living in when he raises a query. Because of the large scale of the whole country, Jaddy feel hopeless to archive such an impossible job, however, in order to gratify his manager, Jaddy is now looking forward to your assistance.
    There might be good news about Jaddy’s work: since Jimmy is very lazy and would not like to travel to a destination whose distance between the original city is larger than TWO. That means only one intermediate city among the route is acceptable (Apparently, all the connecting paths between any two cities, if exists, have the same length as ONE). But don’t be fooled: Jimmy also needs to know that how many alternative different routes are available so that he can have more options. In particular two routes were named as different if and only if there is at least one path in the two routes is distinguishable, moreover, if more than one paths exist between a particular pair of cities, they are considered as distinct.
     
    Input
    Input has multiple test cases. The first line of the input has a single integer T indication the number of test cases, then each test case following. For each test case, the first line contains two integers N and M indication the number of cities and paths in the country. Then M lines are following, each line contains a pair of integers A and B, separated by space, denoting an undirected path between city A and city B, all the cities are numbered from 1 to N. Then a new line contains a single integer Q, which means there are Q queries following. Each query contains a couple of integers A and B which means querying the distance and number of shortest routes between city A and B, each query occupy a single line separately.
    All the test cases are separated by a single blank line.
    You can assume that N, Q <= 100000, M <= 200000.
     
    Output
    For each test case, firstly output a single line contains the case number, then Q lines for the response to queries with the same order in the input. For each query, if there exists at least one routes with length no longer than TWO, then output two integer separated by a single space, the former is the distance (shortest) of routes and the later means how many different shortest routes Jimmy can choose; otherwise, output a single line contains “The pair of cities are not connected or too far away.” (quotes for clarifying). See the sample data carefully for further details.
     
    Sample Input
    2
    5 7
    1 2
    2 3
    3 4
    4 5
    2 5
    2 4
    1 2
    4
    1 4
    1 2
    5 3
    5 4
     
    2 0
    2
    1 1
    1 2
     
    Sample Output
    Case #1:
    2 2
    1 2
    2 2
    1 1
    Case #2:
    0 1
    The pair of cities are not connected or too far away.
     
    给出一个无向图,问 u -> v  距离不超过2的 路径数量有多少 。
    去重边,记录每个点度。
    若询问中u 可直接达到v的话 直接二分出那条边。( log M )
    否则要通过一个中间点 mid , 那么就选择点度比较小的点作为 u 暴力枚举mid。 然后二分 mid -> v 。
    然后可以把这个询问hash起来, 当有相同的询问直接从 hashmap 拿出来 。
     
    对于第2种情况的复杂度来说, 假设 u , v 的点度都达到 M / 2  。 这个询问的复杂度就 M/2*log(M) , 除外其他询问都是 Log(M)
    假设点度都分得很均匀 。 都是 sqrt(M) , 那么这个询问 复杂度就是 sqrt(M) * log(M) 了
     
    总的来说 复杂度就是 Q*sqrt(M)*log(M) .
     
     
    #include<bits/stdc++.h>
    using namespace std ;
    const int N = 100010;
    const int M = 500010;
    const long long K = 100000;
    int n , m ;
    struct node {
        int u , v ;
        long long cnt ;
        bool operator < ( const node &a ) const {
            if( u != a.u ) return u < a.u ;
            else return v < a.v ;
        }
    } e[M] ;
    int tot ;
    int in[N] ;
    const int HASH = 300007;
    struct HASHMAP {
        long long key[N] , f[N] ;
        int head[HASH] , next[N] , size ;
        void init() {
            memset( head , -1 , sizeof head ) ;
            size = 0 ;
        }
        void insert( int u , int v , long long ans ) {
            long long KEY = K * u + v ;
            int c = KEY % HASH ;
            f[size] = ans ;
            key[size] = KEY ;
            next[size] = head[c] ;
            head[c] = size++;
        }
        long long find( int u , int v ) {
            long long KEY = K * u + v ;
            int c = KEY % HASH ;
            for( int i = head[c] ; ~i ; i = next[i] ) {
                if( key[i] == KEY ) return f[i] ;
            }
            return -1 ;
        }
    } mp ;
    
    
    long long find( int u , int v ) {
        int l = 0 , r = m - 1 ;
    //    cout << "l :" << l << " r : " << r << endl ;
        if( l > r ) return -1 ;
        if( u > e[r].u || ( u == e[r].u && v > e[r].v ) ) return -1 ;
        if( v < e[l].v || ( v == e[l].v && u < e[l].u ) ) return -1 ;
        while( l <= r ) {
            int mid = (l+r)>>1;
            if( u < e[mid].u ) {
                r = mid - 1 ;
            }
            else if( u == e[mid].u ) {
                if( v < e[mid].v ) r = mid - 1 ;
                else if( v > e[mid].v ) l = mid + 1 ;
                else return e[mid].cnt ;
            }
            else {
                l = mid + 1 ;
            }
        }
        return -1 ;
    }
    vector< pair<int,long long> >g[N];
    
    void Work() {
        mp.init();
        int q ; cin >> q ;
        while( q-- ) {
            int u , v ; cin >> u >> v ;
            u-- , v-- ;
            if( u > v ) swap( u , v ) ;
            else if( u == v ) { cout << "0 1"<< endl ; continue ; }
            long long ans = find( u , v ) ;
            if( ans != -1 ) {
                cout << "1 " << ans << endl ;
            } else {
                ans = mp.find( u , v ) ;
                if( ans == -1 ) {
                    ans = 0 ;
                    if( in[u] > in[v] ) swap( u , v ) ;
                    for( int i = 0 ; i < g[u].size() ; ++i ) {
                        int mid = g[u][i].first ;
                        long long cnt1 = g[u][i].second , cnt2 = find( min(mid,v) , max(mid,v) );
                        if( cnt2 != -1 ) ans += cnt1 * cnt2 ;
                    }
                    if( u > v ) swap( u , v ) ;
                    mp.insert( u , v , ans ) ;
                }
                if( ans ) cout << "2 " << ans << endl ;
                else cout << "The pair of cities are not connected or too far away." << endl ;
            }
        }
    }
    
    void Gao() {
        memset( in , 0 , sizeof in );
        for( int i = 0 ; i < n ; ++i ) g[i].clear();
        cin >> n >> m ;
        if( !m ) return  ;
        for( int i = 0 ; i < m ; ++i ) {
            int x , y ; cin >> x >> y ;
            x-- , y-- ;
            if( x > y ) swap( x , y ) ;
            e[i].u = x , e[i].v = y , e[i].cnt = 1 ;
            in[x]++ , in[y]++ ;
        }
        sort( e , e + m ) ;
        tot = 1 ;
        for( int i = 1 ; i < m ; ++i ) {
            if( e[tot-1].u == e[i].u && e[tot-1].v == e[i].v ) {
                e[tot-1].cnt++ ;
            } else {
                e[tot++] = e[i] ;
            }
        }
        m = tot ;
        for( int i = 0 ; i < m ; ++i ) {
            g[e[i].u].push_back( make_pair( e[i].v,e[i].cnt) ) ;
            g[e[i].v].push_back( make_pair( e[i].u,e[i].cnt) ) ;
        }
    }
    
    int Run() {
        int _ , cas = 1 ; cin >> _ ;
        while( _-- ) {
            cout << "Case #" << cas++ << ":" << endl ;
            Gao(); Work();
        }
        return 0 ;
    }
    int main() {
        ios::sync_with_stdio(0);
        return Run();
    }
    View Code
     
  • 相关阅读:
    SQL行转列问题
    pgAdmin III 单表数据的导出导入
    window 服务的安装和卸载
    将Excel表格转成DataTable
    “Timeout 时间已到。在操作完成之前超时时间已过或服务器未响应”解决方法
    form-data提交
    由于本公司项目需要,现急需拥有微软MCSE证书的人才,一经录用,待遇从优!
    Head First设计模式悟道
    entityframwork
    .net 开源模板引擎jntemplate 教程:基础篇之在ASP.NET MVC中使用Jntemplate
  • 原文地址:https://www.cnblogs.com/hlmark/p/4389472.html
Copyright © 2011-2022 走看看