版权声明:欢迎转载!拒绝抄袭. https://blog.csdn.net/qq_36257146/article/details/88559812
其实这道题我没有写对~
我一开始写的是UVa 1151,结果是错的,然后看到有个博主说POJ上有道一毛一样的题目,迅速水过,但是到了UVa就各种WA,心里好奇,一提交POJ竟然AC。。。
好吧(╯▽╰),先贴,等我找找原因为什么错再来改改。
#include <iostream>
#include <algorithm>
#include <vector>
#define ll long long
#define maxn 1101
#define inf 0x3f3f3f3f
using namespace std;
struct Edge
{
int u,v,w;
Edge(int i,int j,int k):u(i),v(j),w(k) {}
Edge() {}
const bool operator < (const Edge & a)const
{
return w<a.w;
}
};
struct Node
{
int cost;
vector<Edge>edges;
};
Node nodes[10];
vector<Edge>e,e1;//在套餐之外的边和已经确定的边
int p[maxn],X[maxn],Y[maxn];//点
int n,q;
ll result;
int choose[8][3] = {{0,0,0},{1,0,0},{0,1,0},{0,0,1},{1,1,0},{1,0,1},{0,1,1},{1,1,1}};//八种选择套餐
int Find(int x)
{
return p[x] == x ? x: p[x] = Find(p[x]);
}
//首先kruskal
void kruskal()
{
ll ans = 0;
sort(e.begin(),e.end());
for(int i = 1; i<=n; i++) p[i] = i;
for(int i = 0; i<e.size(); i++)
{
int x = Find(e[i].u);
int y = Find(e[i].v);
if(x!=y)
{
e1.push_back(e[i]);
ans += e[i].w;
p[x] = y;
}
}
}
int getCost(int i,int j)
{
return (X[i]-X[j])*(X[i]-X[j]) + (Y[i]-Y[j])*(Y[i]-Y[j]);
}
void solve(int i)
{
ll ans = 0;
vector<Edge>temp;
for(int j = 0; j<q; j++)
{
if(i&(1<<j))//套餐j
{
Node t = nodes[j];
ans+=t.cost;
for(int k = 0; k<t.edges.size(); k++)
{
temp.push_back(t.edges[k]);
}
}
}
//把原来树中的加进去
for(i = 0; i<e1.size(); i++)
{
temp.push_back(e1[i]);
}
sort(temp.begin(),temp.end());
for(i = 1; i<=n; i++) p[i] = i;
for(int j = 0; j<temp.size(); j++)
{
int x = Find(temp[j].u);
int y = Find(temp[j].v);
if(x!=y)
{
ans+=temp[j].w;
p[x] = y;
}
}
result = min(result,ans);
// for(int j = 0;j<edges.size();j++)
// {
// cout<<edges[j].u<<" "<<edges[j].v<<" "<<edges[j].w<<endl;
// }
// cout<<"+++++++++++++++++"<<endl;
}
int main()
{
int T,num,cost,t;
int a,b;
int temp[maxn];
int kase = 0;
//cin>>T;
//while(T--)
//{
// if(kase++) cout<<endl;
result = inf;
e.clear();e1.clear();
cin>>n>>q;
for(int i = 0; i<q; i++)
{
cin>>num>>nodes[i].cost;
for(int j = 0; j<num; j++)
{
cin>>temp[j];
//nodes[i].points.push_back(t);
}
for(int j = 0;j<num;j++)
{
for(int k = j+1;k<num;k++)
{
a = temp[j];b = temp[k];
nodes[i].edges.push_back(Edge(a,b,0));
}
}
}
//点
for(int i = 1; i<=n; i++)
{
cin>>X[i]>>Y[i];
}
//点与点之间构成边
for(int i = 1; i<=n; i++)
{
for(int j = i+1; j<=n; j++)
{
e.push_back(Edge(i,j,getCost(i,j)));
}
}
kruskal();
for(int i = 0; i<(1<<q); i++)
{
solve(i);
}
cout<<result<<endl;
//}
return 0;
}
/**
1
7 3
2 4 1 16
3 3 3 6 7
3 9 2 4 5
0 2
4 0
2 0
4 2
1 3
0 5
4 4
**/