您的位置:首页 > 其它

uva 12507 Kingdoms(dfs+最小生成树)

2017-06-09 20:36 344 查看
题意:

n(4-16)个点,每个点有权值,m条带权值的边,问在边权最多花费k的情况下,能让1这个点连通的点的权值加和最大为多少。

解题思路:

做题要看数据范围,n个点直接dfs枚举是否取2到n种的每个点,1肯定要取,然后用最小生成树把枚举出来的点连接,看是否能建成生成树,然后再看生成树的权值是否小于等于k,满足的情况算一下点权和,更新一下答案,就做完了。

代码:

#include <bits/stdc++.h>
using namespace std;
int p[105];
int a[105][105];
struct node
{
int x, y;
int c, is;
}edg[105];
int book[105];
int t, n, m, k, i, j, cnt;
int f[105];
int getf(int x)
{
if(f[x]==x)return x;
else return f[x]=getf(f[x]);
}
bool merg(int x, int y)
{
x=getf(x), y=getf(y);
if(x==y)
{
return false;
}
else
{
f[x]=y;
return true;
}
}
bool cmp(node a, node b)
{
return a.c<b.c;
}
int ans;
bool judge()
{
int x, y, c, sum=0;
// printf("cnt%d\n", cnt);
for(i=1; i<=n; i++)f[i]=i;
for(i=1, j=0; i<=m; i++)
{
x=edg[i].x, y=edg[i].y, c=edg[i].c;
/*
if(cnt==3)
{
printf("c%d %d %d\n", c, cnt ,j);
}
*/
if(book[x] && book[y] && merg(x,y))
{
sum+=c;
j++;
}
if(j>=cnt-1)break;
}
return sum<=k && j>=(cnt-1);
}
void dfs(int x)
{
if(x>n)
{
if(judge()==0)
{
return;
}
int sum=0;
for(i=1; i<=n; i++)
{
if(book[i])
{
// printf("%d ", i);
sum+=p[i];
}
}
// printf("%d\n", sum);
ans=max(sum, ans);

return;
}
cnt++;
book[x]=1;
dfs(x+1);
cnt--;
book[x]=0;
dfs(x+1);
return;

}

int main()
{
cin>>t;
while(t--)
{
// memset(a, 0, sizeof a);
memset(book, 0, sizeof book);
ans=0;
scanf("%d%d%d", &n, &m, &k);
for(i=1; i<=n; i++)scanf("%d", &p[i]);
int x, y, c;
for(i=1; i<=m; i++)
{
scanf("%d%d%d", &edg[i].x, &edg[i].y, &edg[i].c);
}
sort(edg+1, edg+m+1, cmp);
book[1]=1;
cnt=1;
dfs(2);
printf("%d\n", ans);

}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: