您的位置:首页 > 其它

[最小k度限制生成树] POJ 1639 Picnic Planning

2016-12-11 10:43 471 查看
论文:汪汀--最小生成树问题的拓展

另见:http://blog.csdn.net/jarily/article/details/8779621 http://www.cnblogs.com/ylfdrib/archive/2010/08/21/1805505.html

主要思想:先求出最小m度限制生成树 由最小m度限制生成树找环得到最小m+1度限制生成树

实现么 Prime/Kruskal dfs/DP 皆可

#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<map>
#include<string>
#include<iostream>
#include<cstring>
#define cl(x) memset(x,0,sizeof(x))
using namespace std;

const int N=105;

struct edges{
int u,v,w,idx;
edges(int u=0,int v=0,int w=0,int idx=0):u(u),v(v),w(w),idx(idx){ }
bool operator < (const edges &B) const{
return w<B.w;
}
}Ed[N*N*2];

map<string,int> Map;

int n,m;

inline int Num(string s){
if (Map.find(s)!=Map.end()) return Map[s];
Map[s]=++n; return n;
}

namespace Tset{
int fat
;
inline void init(int n){
for (int i=1;i<=n;i++) fat[i]=i;
}
inline int Fat(int u){
return u==fat[u]?u:fat[u]=Fat(fat[u]);
}
inline bool Merge(int x,int y){
x=Fat(x); y=Fat(y); if (x==y) return 0;
fat[x]=y; return 1;
}
}

struct edge{
int u,v,w,next;
}G[N*N*2];
int head
,inum=1;
int tag[N*N*2];

inline void add(int u,int v,int w,int p){
G[p].u=u; G[p].v=v; G[p].w=w; G[p].next=head[u]; head[u]=p;
}

int T,K;

int f
;

#define V G[p].v
inline void dfs(int u,int fa){
for (int p=head[u];p;p=G[p].next)
if (V!=fa && tag[p]){
if (u!=1)
if (f[u]==-1 || G[p].w>G[f[u]].w)
f[V]=p;
else
f[V]=f[u];
dfs(V,u);
}
}

int Ans=0;

int main(){
using namespace Tset;
string su,sv; int iu,iv,iw;
freopen("t.in","r",stdin);
freopen("t.out","w",stdout);
while (~scanf("%d",&m)){
Map["Park"]=n=1;
for (int i=1;i<=m;i++){
cin>>su>>sv>>iw; iu=Num(su); iv=Num(sv);
add(iu,iv,iw,++inum); add(iv,iu,iw,++inum);
Ed[i]=edges(iu,iv,iw,i);
}
cin>>K;
sort(Ed+1,Ed+m+1); init(n);
for (int i=1;i<=m;i++){
if (Ed[i].u==1 || Ed[i].v==1) continue;
if (Merge(Ed[i].u,Ed[i].v))
tag[Ed[i].idx<<1]=tag[Ed[i].idx<<1|1]=1,Ans+=Ed[i].w;
}
for (int i=1;i<=m;i++){
if (!(Ed[i].u==1 || Ed[i].v==1)) continue;
if (Merge(Ed[i].u,Ed[i].v))
tag[Ed[i].idx<<1]=tag[Ed[i].idx<<1|1]=1,++T,Ans+=Ed[i].w;
}
for (int i=T+1;i<=K;i++){
memset(f,-1,sizeof(f));
dfs(1,0);
int t,r,maxv=-1<<30;
for (int p=head[1];p;p=G[p].next)
if (!tag[p] && f[V]!=-1 && maxv<G[f[V]].w-G[p].w)
maxv=G[f[V]].w-G[p].w,t=f[V],r=p;
if (maxv<=0) break;
Ans-=maxv;
tag[r]=tag[r^1]=1; tag[t]=tag[t^1]=0;
}
printf("Total miles driven: %d\n",Ans);
cl(head); inum=1; cl(tag); T=0; Ans=0; Map.clear();
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: