poj 1639 Picnic Planning 单度限制的最小生成树

来源:互联网 发布:淘宝忘了用优惠券 编辑:程序博客网 时间:2024/06/05 05:28

题意:

给一个无向图连通图,求它的最小生成树,生成树满足条件点v0的度小于等于limit。

分析:

一般有度限制的最小生成树问题是np完全的,但单点度限制就比较简单了,先在原图上求不含v0的最小生成森林,然后再将森林中每一棵树选一条最短的边连到v0上,设最小生成森林中有k0棵树,如果k0>limit自然无解,否则每次再选增量最小的边连到v0上,同时删除因为加边形成环上的最大边。

代码:

//poj 1639//sepNINE#include <iostream>#include <string>#include <map>#include <algorithm>using namespace std;const int maxN=32;const int maxM=1024;map<string,int> name;int e,parkE,park,n;int vis[maxN];int f[maxN],used[maxM],usedParkE[maxM];int g[maxN][maxN],parent[maxN];struct Edge{int u,v,w;}edge[maxM],parkEdge[maxM];int cmp(Edge a,Edge b){return a.w<b.w;}int find(int u){return f[u]==u?u:f[u]=find(f[u]);}void dfs(int u){for(int i=1;i<=n;++i)if(g[u][i]>0&&parent[i]==0){parent[i]=u;dfs(i);}}void updateTree(){memset(parent,0,sizeof(parent));parent[park]=-1;dfs(park);}int findmax(int v){int maxx=-1,x;while(v!=park){if(maxx<g[v][parent[v]]){maxx=g[v][parent[v]];x=v;}v=parent[v];}return x;}int main(){int i,m,limit;n=0;e=parkE=0;park=-1; cin>>m;while(m--){string a,b;int w;cin>>a>>b>>w;if(name[a]==0) name[a]=++n;if(name[b]==0) name[b]=++n;if(a=="Park") park=name[a];if(b=="Park") park=name[b];int u=name[a],v=name[b];if(park==u||park==v){parkEdge[parkE].u=u;parkEdge[parkE].v=v;parkEdge[parkE].w=w;++parkE;}else{edge[e].u=u;edge[e].v=v;edge[e].w=w;++e;}}cin>>limit;sort(edge,edge+e,cmp);for(i=1;i<=n;++i) f[i]=i;int sum=0;memset(used,0,sizeof(used));memset(g,0,sizeof(g));for(i=0;i<e;++i){int u=edge[i].u,v=edge[i].v;int pa=find(u);int pb=find(v);if(pa==pb)continue;used[i]=1;g[u][v]=g[v][u]=edge[i].w;f[pa]=pb;sum+=edge[i].w; }memset(vis,0,sizeof(vis));sort(parkEdge,parkEdge+parkE,cmp);memset(usedParkE,0,sizeof(usedParkE));int cnt=0;for(i=0;i<parkE;++i){int u=parkEdge[i].u;int v=parkEdge[i].v;int w=parkEdge[i].w;if(u!=park) swap(u,v);if(vis[find(v)]==0){++cnt;vis[find(v)]=1;usedParkE[i]=1;sum+=w;g[u][v]=g[v][u]=w;}}updateTree();while(cnt<limit){int deta=0,minI;for(i=0;i<parkE;++i){if(usedParkE[i]==1)continue;int u=parkEdge[i].u,v=parkEdge[i].v,w=parkEdge[i].w;if(u!=park) swap(u,v);int changeP=findmax(v);int pFather=parent[changeP];if(pFather==park)continue;int t=w-g[changeP][pFather];if(t<deta){deta=t;minI=i;}}if(deta==0)break;else{int u=parkEdge[minI].u;int v=parkEdge[minI].v;int w=parkEdge[minI].w;if(u!=park) swap(u,v);int changeP=findmax(v);int pFather=parent[changeP];g[changeP][pFather]=g[pFather][changeP]=0;g[u][v]=g[v][u]=w;updateTree();usedParkE[minI]=1;sum+=deta;++cnt;} }printf("Total miles driven: %d",sum);return 0;} 


0 0
原创粉丝点击