今天看了 一道 有度数限制的最小生成树题目,按照书上给出的思路写的代码,思路的最后一步没有实现,可能没弄懂书上的意思。
http://poj.org/problem?id=1639。
题意:
大概是说在一张无向图中找一颗最小生成树,该树一定包含某“1”点,且该点的度数不能超过某值。
思路:
先不考虑“1”点,对原图 dfs划分联通块,然后从每个联通块中找一条与“1”最近的路径添加到答案中。下一步在联通块内部求最小生成树。
最后,遍历“1”点的所有边,如果某条边指向的终点不是已经生成的生成树的起点,判断其是否小于 已有生成树中从该点到“1”点路径中的最长边长度。有,替换旧边,,,直到找不到这样的边(最后这个地方理解的还有点问题)。
先把没写完的代码放在这里:
#include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include<algorithm>
#include <set>
#include <queue>
#include <stack>
#include<vector>
#include<map>
#include<ctime>
#define ll long long
using namespace std;
const int N=36;
int v[N];//联通块标号
int ver[N];//邻接表边N的终点
int edge[N*N+100];//邻接表边N的权值
int head[N];//邻接表点N的最后一条边
int next[N];//邻接表点边N的下一条边
int tot;//邻接表 中边数
int cnt;//联通块的数目
void add(int x,int y,int z)//邻接表加边
{
ver[++tot]=y;
edge[tot]=z;
next[tot]=head[x];
head[x]=tot;
}
void dfs(int x)//得到x所在的联通块
{
v[x]=cnt;
for(int i=head[x];i;i=next[i])
{
int y=ver[i];
if(v[y])continue;
dfs(y);
}
}
int dis[N][N];
map<string,int>mm;
int num;
int d[N];//prime中以点N为终点的那条边;
bool flag[N];
int prime(int index,int pos,int nn)//联通块标号、起点
{
memset(d,0,sizeof(d));
memset(flag,0,sizeof(flag));
d[pos]=0;
for(int i=1;i<nn;++i)
{
int x=0;
for(int j=1;j<=num;++j)
if(!flag[j]&&((x==0)||d[j]<d[x])&&v[j]==index)x=j;
flag[x]=1;
for(int y=1;y<=num;++y)
{
if(!flag[y]&&v[y]==index)d[y]=min(d[y],dis[x][y]);
}
}
int ans=0;
for(int i=1;i<=num;++i)
{
if(v[i]==index)ans+=d[i];
}
return ans;
}
int main()
{
int n;
while(cin>>n)
{
memset(dis,0,sizeof(dis));
tot=cnt=0;
mm.clear();
memset(v,0,sizeof(v));
memset(ver,0,sizeof(ver));
memset(head,0,sizeof(head));
memset(next,0,sizeof(next));
memset(edge,0,sizeof(edge));
string s,t;
int x;
mm.insert(make_pair("Park",1));
num++;
for(int i=1;i<=n;++i)
{
cin>>s>>t>>x;
int d1,d2;
if(mm.find(s)==mm.end())
{
num++;
mm.insert(make_pair(s,num));
d1=num;
}
else
{
d1=mm.find(s)->second;
}
if(mm.find(t)==mm.end())
{
num++;
mm.insert(make_pair(t,num));
d2=num;
}
else
{
d2=mm.find(t)->second;
}
dis[d1][d2]=dis[d2][d1]=x;
add(d1,d2,x);
}
int s;
cin>>s;
for(int i=2;i<=num;++i)
{
if(v[i])continue;
cnt++;
dfs(i);
}
/*if(cnt>s)
{
//无解
}*/
int ans=0;
for(int i=1;i<=cnt;++i)
{
int minn=999999999;
int pos;
for(int j=1;j<=num;++j)
{
int nn=0;
if(v[j]==i)
{
nn++;
if(dis[j][1]<minn)minn=dis[j][1],pos=j;
}
}
if(minn!=999999999)ans+=minn;
ans+=prime(i,pos,nn);
}
}
}