HDU 2433 (最短路+BFS+剪枝)

http://acm.hdu.edu.cn/showproblem.php?pid=2433

这个问题因为路径都是1,所以可以用bfs遍历

可以看这几篇文章讲解:

http://blog.csdn.net/panyanyany/article/details/7215069

(这篇代码非常清晰,而且效率很高)

http://www.cppblog.com/keroro/archive/2013/05/27/200622.html?opt=admin

  1 #include <cstdio>
  2 #include <queue>
  3 #include <vector>
  4 using namespace std;
  5 
  6 #define MEM(a,v) memset (a,v,sizeof(a))
  7 // a for address, v for value
  8 
  9 #define max(x,y) ((x)>(y)?(x):(y))
 10 #define max(x,y) ((x)>(y)?(x):(y))
 11 
 12 const int L = 1010;
 13 const int INF = 1<<27;
 14 
 15 bool    used[L], bCnet, bInit ;
 16 int     n, m ;
 17 int     dist[L], map[L][L], sum_d[L], pre[L][L];
 18 
 19 
 20 //边表
 21 struct Edge
 22 {
 23           int u,v;
 24 };
 25 
 26 Edge e[30*L];
 27 
 28 
 29 int bfs(int beg)
 30 {
 31           MEM(used,false);
 32           MEM(dist,0);
 33 
 34           used[beg] = true;
 35 
 36           queue<int> q;
 37           q.push(beg);
 38 
 39           int i;
 40 
 41           while(!q.empty())
 42           {
 43                     int t = q.front();
 44                     q.pop();
 45                     for(i = 1;i<=n;i++)
 46                     {
 47                               if(!used[i] && map[t][i])
 48                               {
 49                                         used[i] = true;
 50                                         dist[i] = dist[t]+1;
 51 
 52                                         //初始化    bInit =true
 53                                         //初始化后  bfs = false
 54                                         if(bInit)
 55                                                   pre[beg][i] = t;
 56                                         //pre储存的是beg树里面,i的上一个元素
 57                                         //这样只需判断pre[x][u] ==v 和pre[x][v] == u
 58                                         //就可以知道x树里面有没有uv边
 59 
 60                                         q.push(i);
 61                               }
 62                     }
 63           }
 64 
 65           int sum = 0;
 66 
 67 
 68           //求出点beg到各边的距离和
 69           // 从 beg+1 开始 和从 1 开始,效果差不多
 70           for(i = beg+1;i<=n;i++)
 71           {
 72                     if(!dist[n])
 73                               return INF;
 74                     else
 75                               sum+=dist[i];
 76           }
 77           return sum;
 78 
 79 }
 80 
 81 
 82 
 83 int main()
 84 {
 85           int i,j;
 86 
 87           int u,v,sum,res;
 88 
 89           while(~scanf("%d%d",&n,&m))
 90           {
 91                     MEM(map,0);
 92                     MEM(pre,0);
 93 
 94                     for(i = 1;i<=m;i++)
 95                     {
 96                               scanf("%d%d",&u,&v);
 97                               map[u][v] = ++map[v][u];
 98 
 99                               //如果有重复边的话,map为2
100 
101                               e[i].u = v;
102                               e[i].v = u;
103                     }
104 
105                     sum = 0;
106                     bInit = true;
107                     bCnet = true;
108 
109 
110                     //求出每个点到其他点的距离和
111                     for(i = 1;i<=n;i++)
112                     {
113                               sum_d[i] = bfs(i);
114                               sum+=sum_d[i];
115 
116                               if(sum>=INF)
117                               {
118                                         bCnet = false;
119                                         break;
120                               }
121                     }
122 
123                     bInit = false;
124 
125 
126                     //删除边
127                     for(i = 1;i<=m;i++)
128                     {
129                               //uv为删除的边
130                               u = e[i].u;
131                               v = e[i].v;
132 
133                               // map[u][v] 判断有无重边,可以优化300多MS
134                               if(bCnet && map[u][v] == 1)
135                               {
136                                         res = 0;
137                                         for(j = 1;j<=n;j++)
138                                         {
139                                                   //j树里不存在删除的边
140                                                   // 最重要的剪枝,否则直接超时
141                                                   if(pre[j][u] != v && pre[j][v] !=u)
142                                                   {
143                                                             res += sum_d[j];
144                                                   }
145                                                   else
146                                                   {
147                                                             //存在uv边,j树重新bfs
148                                                             --map[u][v];
149                                                             --map[v][u];
150                                                             res += bfs(j);
151                                                             ++map[u][v];
152                                                             ++map[v][u];
153 
154                                                             if(res >= INF)
155                                                                       break;
156 
157                                                   }
158 
159                                         }
160 
161 
162 
163                               }
164                               else
165                                         res=sum;
166 
167                               if(res >= INF)
168                                         puts("INF");
169                               else
170                                         printf("%d
",res*2);
171 
172                     }
173 
174 
175           }
176 
177           return 0;
178 }
原文地址:https://www.cnblogs.com/qlky/p/5018096.html