POJ1639:Picnic Planning

——problem:度限制生成树

——solution:Kruskal

算法框架:

1. 先求出最小m度限制生成树;

2. 由最小m度限制生成树得到最小m+1度限制生成树;

3. dT(v0)=k时停止(即当V0的度为k的时候停止)

 

第一步:求解最小m度限制生成树:原图中去掉和V0相连的所有边,得到m个连通分量,而这个连通分量必须通过v0来连接,所以,在图的所有生成树中dT(v0)≥m。也就是说,当k<m时,问题无解。对每个连通分量求一次最小生成树,对于每个连通分量V’,求一点v1v1∈V',ω(v0,v1)=min{ω(v0,v')|v'∈V'},则该连通分量通过边(v1,v0)v0相连。于是,我们就得到了一个m度限制生成树,不难证明,这就是最小m度限制生成树。

 

第二步:由最小m度限制生成树,得到最小m+1度限制生成树,连接和V0相邻的点v,则可以知道一定会有一个环出现,只要找到这个环上的最大权边,用边(V0, v)替换掉,就可以得到一个m+1度限制生成树,枚举所有和V0相邻点v,找到替换后增加权值最小的一次替换,就可以求得m+1度限制生成树。。如果每添加一条边,都需要对环上的边一一枚

举,时间复杂度将比较高,这里,动态规划就有了用武之地。设Best(v)为路径v0—v上与v0无关联且权值最大的边。定义father(v)v的父结点,动态转移方程:Best(v)=max(Best(father(v)),ω(father(v),v)),边界条件为Best[v0]=-∞Best[v’]=-∞| (v0,v’)∈E(T)

 

第三步:当度为K的时候就可以退出了。

View Code
1 #include<stdio.h>
2 #include<map>
3 #include<string>
4 #include<string.h>
5 #include<memory.h>
6  using namespace std;
7 #define N 30
8 #define M 500
9 map<string, int, less<string> > h;
10 struct node
11 {
12 int u, v, l;
13 } edge[M],max_edge[N];
14 string name;
15 int i, j, d, loc, n, m, l, p, t, ans, temp, sum, v0, oo;
16 bool vis[N];
17 char name1[20], name2[20];
18 int tree[N][N], f[N], set_to_v0[N], from[N], g[N][N];
19 int cmp(const void *a, const void *b)
20 {
21 return (*(node *) a).l - (*(node *) b).l;
22 }
23 int max(int a, int b)
24 {
25 return a > b ? a : b;
26 }
27 int min(int a, int b)
28 {
29 return a < b ? a : b;
30 }
31 int add_name(string name)
32 {
33 if (h.find(name) == h.end())
34 {
35 n++;
36 h.insert(pair<string, int> (name, n));
37 return n;
38 }
39 return h[name];
40 }
41 int getf(int u)
42 {
43 int temp;
44 temp = f[u];
45 if (temp != u)
46 temp = getf(temp);
47 f[u] = temp;
48 return temp;
49 }
50 void Kruskal()
51 {
52 int i, u, v, fu, fv;
53 for (i = 1; i <= n; i++)
54 f[i] = i;
55 sum = 0;
56 for (i = 0; i < m; i++)
57 {
58 u = edge[i].u;
59 v = edge[i].v;
60 fu = getf(u);
61 fv = getf(v);
62 if (fu != fv && v != v0 && u != v0)
63 {
64 f[fu] = fv;
65 sum += edge[i].l;
66 tree[u][v]=edge[i].l;
67 tree[v][u]=edge[i].l;
68 }
69 }
70 }
71 void dfs(int u, int fa)
72 {
73 int i;
74 if (u == fa)
75 max_edge[u].l = 0;
76 for (i = 1; i<=n;i++)
77 {
78 if (i== v0 ||i == fa||tree[u][i]==oo)
79 continue;
80 if (max_edge[u].l<tree[u][i])
81 {
82 max_edge[i].l=tree[u][i];
83 max_edge[i].u=u;
84 max_edge[i].v=i;
85 }
86 else
87 {
88 max_edge[i].l=max_edge[u].l;
89 max_edge[i].u=max_edge[u].u;
90 max_edge[i].v=max_edge[u].v;
91 }
92 dfs(i, u);
93 }
94 }
95 int main()
96 {
97 scanf("%d", &m);
98 memset(g, 0x1f, sizeof(g));
99 memset(tree, 0x1f, sizeof(tree));
100 oo = g[0][0];
101 t = 0;
102 h.clear();
103 for (i = 0; i < m; i++)
104 {
105 scanf("%s %s %d", name1, name2, &edge[i].l);
106 name = name1;
107 edge[i].u = add_name(name);
108 name = name2;
109 edge[i].v = add_name(name);
110 g[edge[i].u][edge[i].v] = g[edge[i].v][edge[i].u] = edge[i].l;
111 if (strcmp(name1, "Park") == 0)
112 v0 = edge[i].u;
113 if (strcmp(name2, "Park") == 0)
114 v0 = edge[i].v;
115 }
116 scanf("%d", &p);
117 qsort(edge, m, sizeof(edge[0]), cmp);
118 Kruskal();
119 memset(set_to_v0, 0x1f, sizeof(set_to_v0));
120 for (i = 1; i <= n; i++)
121 {
122 f[i] = getf(i);
123 if (set_to_v0[f[i]] > g[i][v0])
124 {
125 set_to_v0[f[i]] = g[i][v0];
126 from[f[i]] = i;
127 }
128 }
129 d = 0;
130 for (i = 1; i <= n; i++)
131 if (set_to_v0[i] < oo)
132 {
133 d++;
134 sum += set_to_v0[i];
135 tree[v0][from[i]]=set_to_v0[i];
136 tree[from[i]][v0]=set_to_v0[i];
137 dfs(from[i], from[i]);
138 }
139 ans=sum;
140 for (i=d+1;i<=p;i++)
141 {
142 temp=oo;
143 for (j=1;j<=n;j++)
144 if (g[v0][j]<oo&&tree[v0][j]==oo)
145 if (sum+g[v0][j]-max_edge[j].l<temp)
146 {
147 temp=sum+g[v0][j]-max_edge[j].l;
148 loc=j;
149 }
150 tree[v0][loc]=g[v0][loc];
151 tree[loc][v0]=g[v0][loc];
152 tree[max_edge[loc].u][max_edge[loc].v]=oo;
153 tree[max_edge[loc].v][max_edge[loc].u]=oo;
154 for (j=1;j<=n;j++)
155 if (tree[v0][j]<oo)
156 dfs(j,j);
157 ans=min(ans,temp);
158 sum=temp;
159 }
160 printf("Total miles driven: %d\n", ans);
161 return 0;
162 }

posted on 2011-03-26 21:43  风也轻云也淡  阅读(268)  评论(0编辑  收藏  举报