当前位置: 代码迷 >> 综合 >> poj 1639 Picnic Planning 单度限制的最小生成树
  详细解决方案

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

热度:94   发布时间:2024-01-19 06:23:04.0

题意:

给一个无向图连通图,求它的最小生成树,生成树满足条件点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;	
} 


  相关解决方案