Why so serious? --[NKU]schindlerlee

2010年02月28日星期日.sgu145 dfs + 二分

2010年02月28日星期日.sgu145
sgu145:dfs + 二分
话说这个思路是看别人的思路看来的,我就想A*啥的了,结果才发现是不重复的第k最短路。
没有发现还能这么搞。
二分第k长路的值,然后搜有多少条路的值小于等于k。这样能得到一个第k条最短路的值,然后再搜一次,
把这个值输出出来即可。
关键是这个思路不好想,代码的话,注意搜有多少条路小于等于k时剪枝优化。
 1 
 2 const int N = 128;
 3 int src, des, n, m, K, vis[N], cnt, mid;
 4 vector < int >g[N];
 5 #define pb(x) push_back(x)
 6 
 7 void dfs(int u, int cost)
 8 {
 9   if (u == des) {
10       if (cost <= mid) {
11           cnt++;
12       }
13       return;
14   }
15 
16   int sz = g[u].size();
17   for (int i = 0; i < sz; i += 2) {
18       int v = g[u][i];
19       int w = g[u][i + 1];
20       if (!vis[v] && cost + w <= mid) {
21           vis[v] = true;
22           dfs(v, cost + w);
23           vis[v] = false;
24       }
25       if (cnt >= K) {    //pruning
26           return;
27       }
28   }
29 }
30//http://www.cppblog.com/schindlerlee
31 void pathcnt()
32 {
33   memset(vis, 0sizeof(vis)), cnt = 0;
34   vis[src] = true;
35   dfs(src, 0);
36 }
37 
38 int out[N],top,ans;
39 bool dfs2(int u, int cost)
40 {
41   if (u == des) {
42       if (cost == ans) {
43           out[top++= u;
44           return true;
45       }
46       return false;
47   }
48 
49   int sz = g[u].size();
50   for (int i = 0; i < sz; i += 2) {
51       int v = g[u][i];
52       int w = g[u][i + 1];
53       if (!vis[v] && cost + w <= ans) {
54           vis[v] = true;
55           if (dfs2(v, cost + w)) {
56               out[top++= u;
57               return true;
58           }
59           vis[v] = false;
60       }
61   }
62   return false;
63 }
64 
65 
66 int main()
67 {
68   int i, j, a, b, c;
69   scanf("%d%d%d"&n, &m, &K);
70   for (i = 0; i < m; i++) {
71       scanf("%d %d %d"&a, &b, &c);
72       g[a].pb(b), g[a].pb(c);
73       g[b].pb(a), g[b].pb(c);
74   }
75 
76   scanf("%d%d"&src, &des);
77   int left = 1, right = 1000001;
78   while (left < right) {
79       mid = (left + right) >> 1;
80       pathcnt();
81       if (cnt < K) {
82           left = mid + 1;
83       } else {
84           right = mid;
85       }
86   }
87   ans = left;
88   memset(vis,0,sizeof(vis)), vis[src] = true;
89   assert(dfs2(src,0));
90   printf("%d %d\n",ans,top);
91   for (i = top - 1;i >= 0;i --) {
92       printf("%d ",out[i]);
93   }
94   printf("\n");
95   return 0;
96 }
97 

posted on 2010-02-28 20:51 schindlerlee 阅读(1292) 评论(0)  编辑 收藏 引用 所属分类: 解题报告


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理