zoukankan      html  css  js  c++  java
  • HDU 3870 Catch the Theves(平面图最小割转最短路径)

    Problem Description
    A group of thieves is approaching a museum in the country of zjsxzy,now they are in city A,and the museum is in city B,where keeps many broken legs of zjsxzy.Luckily,GW learned the conspiracy when he is watching stars and told it to zjsxzy.
    Zjsxzy decided to caught these thieves,and he let the police to do this,the police try to catch them on their way from A to B. Although the thieves might travel this way by more than one group, zjsxzy's excellent police has already gather the statistics that the cost needed on each road to guard it. 
    Now ,zjsxzy's conutry can be described as a N*N matrix A,Aij indicates the city(i,j) have bidirectionals road to city(i+1,j) and city(i,j+1),gurad anyone of them costs Aij.
    Now give you the map,help zjsxzy to calculate the minimium cost.We assume thieves may travel in any way,and we will catch all passing thieves on a road if we guard it.
     
    Input
    The first line is an integer T,followed by T test cases.
    In each test case,the first line contains a number N(1<N<=400).
    The following N lines,each line is N numbers,the jth number of the ith line is Aij.
    The city A is always located on (1,1) and the city B is always located on (n,n).
    Of course,the city (i,j) at the last row or last line won't have road to (i,j+1) or (i+1,j).
     
    Output
    For each case,print a line with a number indicating the minimium cost to arrest all thieves.
     
    Sample Input
    1 3 10 5 5 6 6 20 4 7 9
     
    Sample Output
    18 

    几乎超时,1800+ms,之前TLE了无数次,貌似是因为head后面写了MAXM然后memset多次用的时间太多了

    此题为求最小割,但点数太大,注意到是平面图,可以转化为最短路径模型,详细方法可以看周冬的论文《两极相通——浅析最大—最小定理在信息学竞赛中的应用》

    SPFA代码如下

    #include <cstdio>     
    #include <queue>     
    #include <cstring>     
    #define INF 0x3fffffff     
    #define MAXN 200000     
    #define MAXM 1500010     
    using namespace std;     
              
    int d[MAXN] ,head[MAXN], to[MAXM], next[MAXM], cost[MAXM], ecnt;     
    bool vis[MAXN];     
              
    inline void addEdge(int u, int v, int w)     
    {     
        next[ecnt]=head[u];head[u]=ecnt;     
        to[ecnt]=v;cost[ecnt++]=w;     
    }     
              
    void spfa(int S, int T){     
        for(int i = 0; i <= T; ++i) d[i] = INF;     
        queue<int> Q;     
        Q.push(S);     
        vis[S]=1;     
        d[S] = 0;     
        while(!Q.empty()){     
            int u = Q.front(); Q.pop();     
            vis[u] = 0;     
            for(int p = head[u]; p; p = next[p]){     
                if(d[to[p]] > d[u] + cost[p]){     
                    d[to[p]] = d[u] + cost[p];     
                    if(!vis[to[p]]){     
                        vis[to[p]]=1;     
                        Q.push(to[p]);     
                    }     
                }     
            }     
        }     
        printf("%d\n",d[T]);     
    }     
    int main()     
    {     
        int T, i, j, x, n, ss, tt;     
        scanf("%d",&T);     
        while(T--){     
            scanf("%d",&n);     
            ss = (n-1)*(n-1); tt = ss +1;     
            memset(head, 0, (tt+1)*sizeof(int));     
            ecnt = 1;     
            for(i = 0; i < n; ++i)     
                for(j = 0; j < n; ++j){     
                    scanf("%d",&x);     
                    if(j != n-1){     
                        if(i == 0) addEdge(ss,i*(n-1)+j,x);     
                        else if(i == n-1) addEdge((i-1)*(n-1)+j,tt,x);     
                        else {addEdge(i*(n-1)+j,(i-1)*(n-1)+j,x);addEdge((i-1)*(n-1)+j,i*(n-1)+j,x);}     
                    }     
                    if(i != n-1){     
                        if(j == 0) addEdge(i*(n-1)+j,tt,x);     
                        else if(j == n-1) addEdge(ss,i*(n-1)+j-1,x);     
                        else {addEdge(i*(n-1)+j,i*(n-1)+j-1,x);addEdge(i*(n-1)+j-1,i*(n-1)+j,x);}     
                    }     
                }     
            spfa(ss, tt);     
        }     
        return 0;     
    }
    SPFA

    下面是dijkstra+heap+STL的做法,原来是218ms,后来把scanf改成了getInt,立马变成93ms,这差距大得惊人啊……

     1 #include <cstdio>    
     2 #include <queue>    
     3 #include <cstring>    
     4 #define INF 0x3fffffff    
     5 #define MAXN 200000    
     6 #define MAXM 1500010    
     7 using namespace std;    
     8         
     9 int dis[MAXN] ,head[MAXN], to[MAXM], next[MAXM], cost[MAXM], ecnt;    
    10 bool vis[MAXN];    
    11         
    12 inline void addEdge(int u, int v, int w)    
    13 {    
    14     next[ecnt]=head[u];head[u]=ecnt;    
    15     to[ecnt]=v;cost[ecnt++]=w;    
    16 }    
    17         
    18 void dijkstra(int s, int t)    
    19 {    
    20     for(int i = 0; i <= t; ++i) dis[i] = INF;    
    21     memset(vis,0,sizeof(vis));    
    22     priority_queue<pair<int,int> > que;    
    23     dis[s] = 0;    
    24     que.push(make_pair(0,s));    
    25     while(!que.empty()){    
    26         int u = que.top().second; que.pop();    
    27         if(vis[u]) continue;    
    28         vis[u] = true;    
    29         if(u == t) break;    
    30         for(int p = head[u]; p; p = next[p]){    
    31             if(dis[to[p]] > dis[u] + cost[p]){    
    32                 dis[to[p]] = dis[u] + cost[p];    
    33                 que.push(make_pair(-dis[to[p]],to[p]));    
    34             }    
    35         }    
    36     }    
    37     printf("%d\n",dis[t]);    
    38 }    
    39         
    40 int getInt(){    
    41     char ch=getchar();    
    42     while(ch<'0'||ch>'9')ch=getchar();    
    43     int num=0;    
    44     while(ch>='0'&&ch<='9'){    
    45         num=num*10+ch-'0';    
    46         ch=getchar();    
    47     }    
    48     return num;    
    49 }    
    50         
    51 int main()    
    52 {    
    53     int T, i, j, x, n, ss, tt;    
    54     scanf("%d",&T);    
    55     while(T--){    
    56         scanf("%d",&n);    
    57         ss = (n-1)*(n-1); tt = ss +1;    
    58         memset(head, 0, (tt+1)*sizeof(int));    
    59         ecnt = 1;    
    60         for(i = 0; i < n; ++i)    
    61             for(j = 0; j < n; ++j){    
    62                 x = getInt(); //scanf("%d",&x);    
    63                 if(j != n-1){    
    64                     if(i == 0) addEdge(ss,i*(n-1)+j,x);    
    65                     else if(i == n-1) addEdge((i-1)*(n-1)+j,tt,x);    
    66                     else {addEdge(i*(n-1)+j,(i-1)*(n-1)+j,x);addEdge((i-1)*(n-1)+j,i*(n-1)+j,x);}    
    67                 }    
    68                 if(i != n-1){    
    69                     if(j == 0) addEdge(i*(n-1)+j,tt,x);    
    70                     else if(j == n-1) addEdge(ss,i*(n-1)+j-1,x);    
    71                     else {addEdge(i*(n-1)+j,i*(n-1)+j-1,x);addEdge(i*(n-1)+j-1,i*(n-1)+j,x);}    
    72                 }    
    73             }    
    74         dijkstra(ss, tt);    
    75     }    
    76     return 0;    
    77 }
    dijkstra+heap

    后记:

    后来为SPFA加入了其两个优化,先加入了优化SLF(Small Label First),时间降低至1343MS,后加入优化LLL(Large Label Last)时间降至562MS,再加入getInt,时间降至421MS

    看来在这里还是比不上dijkstra+heap啊……

    代码:

     1 #include <cstdio>  
     2 #include <queue>  
     3 #include <cstring>  
     4 #define INF 0x3fffffff  
     5 #define MAXN 200000  
     6 #define MAXM 1500010  
     7 #define LL long long  
     8 using namespace std;  
     9      
    10 int d[MAXN] ,head[MAXN], to[MAXM], next[MAXM], cost[MAXM], ecnt;  
    11 bool vis[MAXN];  
    12      
    13 inline void addEdge(int u, int v, int w)  
    14 {  
    15     next[ecnt] = head[u]; head[u] = ecnt;  
    16     to[ecnt] = v; cost[ecnt++] = w;  
    17 }  
    18      
    19 void spfa(int S, int T){  
    20     for(int i = 0; i <= T; ++i) d[i] = INF;  
    21     deque<int> Q; LL cntque = 1, sumque = 0;  
    22     Q.push_back(S);  
    23     vis[S]=1;  
    24     d[S] = 0;  
    25     while(!Q.empty()){  
    26         int u = Q.front(); Q.pop_front();  
    27         if(d[u] * cntque > sumque) {Q.push_back(u); continue;}//LLL optimization  
    28         sumque -= d[u]; cntque--;  
    29         vis[u] = 0;  
    30         for(int p = head[u]; p; p = next[p]){  
    31             if(d[to[p]] > d[u] + cost[p]){  
    32                 d[to[p]] = d[u] + cost[p];  
    33                 if(d[to[p]] < d[Q.front()]){//SLF optimization  
    34                     Q.push_front(to[p]);  
    35                     sumque += d[to[p]]; cntque++;  
    36                 } else
    37                     if(!vis[to[p]]){  
    38                         vis[to[p]]=1;  
    39                         Q.push_back(to[p]);  
    40                         sumque += d[to[p]]; cntque++;  
    41                     }  
    42             }  
    43         }  
    44     }  
    45     printf("%d\n",d[T]);  
    46 }  
    47      
    48 int getInt(){  
    49     char ch = getchar();  
    50     while(ch<'0'||ch>'9')ch = getchar();  
    51     int num = 0;  
    52     while(ch >= '0' && ch <= '9'){  
    53         num = num*10 + ch - '0';  
    54         ch = getchar();  
    55     }  
    56     return num;  
    57 }  
    58      
    59 int main()  
    60 {  
    61     int T, i, j, x, n, ss, tt;  
    62     scanf("%d",&T);  
    63     while(T--){  
    64         scanf("%d",&n);  
    65         ss = (n-1)*(n-1); tt = ss +1;  
    66         memset(head, 0, (tt+1)*sizeof(int));  
    67         ecnt = 1;  
    68         for(i = 0; i < n; ++i)  
    69             for(j = 0; j < n; ++j){  
    70                 x = getInt();//scanf("%d",&x);  
    71                 if(j != n-1){  
    72                     if(i == 0) addEdge(ss,i*(n-1)+j,x);  
    73                     else if(i == n-1) addEdge((i-1)*(n-1)+j,tt,x);  
    74                     else {addEdge(i*(n-1)+j,(i-1)*(n-1)+j,x);addEdge((i-1)*(n-1)+j,i*(n-1)+j,x);}  
    75                 }  
    76                 if(i != n-1){  
    77                     if(j == 0) addEdge(i*(n-1)+j,tt,x);  
    78                     else if(j == n-1) addEdge(ss,i*(n-1)+j-1,x);  
    79                     else {addEdge(i*(n-1)+j,i*(n-1)+j-1,x);addEdge(i*(n-1)+j-1,i*(n-1)+j,x);}  
    80                 }  
    81             }  
    82         spfa(ss, tt);  
    83     }  
    84     return 0;  
    85 }
    SPFA优化版
  • 相关阅读:
    df、du、fdisk 规格严格
    云计算 规格严格
    RARLinux 规格严格
    CentOS 规格严格
    NetBeans 时事通讯(刊号 # 22 Aug 18, 2008)
    Single SignOn Integrating Liferay With CAS Server
    Single SignOn Integrating Liferay With CAS Server
    Liferay SSO CAS 集成
    NetBeans 时事通讯(刊号 # 21 Aug 13, 2008 )
    Liferay SSO CAS 集成
  • 原文地址:https://www.cnblogs.com/oyking/p/3116657.html
Copyright © 2011-2022 走看看