/* 题意:有n个点,现在需要联通所有,有q种套餐可以选择, 当然套餐之外也可以自己添加边,意为达到最短距离。 题意很明显,不知道需要使用哪一种套餐, 那么需要枚举每一种套餐的情况。 然后再进行对比。 注意最开始没有套餐的情况。 */ #include<cstdio> #include<iostream> #include<algorithm> #include<vector> using namespace std; const int maxn = 1100; class Cor { public: int x,y; }cor[maxn]; //坐标 class Node { public: int x,y; int dis; }edge[maxn*maxn]; //边 vector<int>t[10]; int cost[10]; //每中套餐的花费 int n,m,q; int f[maxn]; bool cmp(Node a,Node b) { return a.dis < b.dis; } double distances(Cor a,Cor b) { int dx = a.x - b.x; int dy = a.y - b.y; return (dx*dx + dy*dy); } void inti(int n) { for(int i = 0;i <= n; i++) f[i] = i; return ; } int Find(int x) { int r = x; while(r != f[r]) r = f[r]; int i = x,j; while(f[i] != r){ j = f[i]; f[i] = r; i = j; } return r; } int merge(int x,int y) { int a = Find(x); int b = Find(y); if(a == b) return false; else f[a] = b; return true; } int kruskal() //标准的kruskal { int pos = 0,sum = 0; for(int i = 0;i < m && pos < n - 1; i++){ if(merge(edge[i].x,edge[i].y)){ pos++; sum += edge[i].dis; } } return sum; } void solve() { inti(n); int ans = kruskal(); //初始的情况 for(int i = 0;i < (1<<q); i++){ int money = 0; inti(n); for(int j = 0;j < q; j++){ //枚举每一种套餐的情况 // if((i>>j)&1) continue; if(i&(1<<j)){ money += cost[j]; for(int k = 1;k < t[j].size(); k++){ merge(t[j][k],t[j][0]); //把套餐的点相连 } } } ans = min(ans,kruskal() + money); } printf("%d\n",ans); return ; } int main() { // freopen("in.txt","r",stdin); int ncase,pn = 1; scanf("%d",&ncase); while(ncase--){ if(pn > 1) //UVA的输出 printf("\n"); pn++; for(int i = 0;i < 10; i++) //要清理,初始化 t[i].clear(); scanf("%d%d",&n,&q); for(int i = 0;i < q; i++){ //vector是把每一种套餐记录, // 因为不知道每一种套餐有几个点,所以用vector很合适 int num,temp; scanf("%d%d",&num,&cost[i]); for(int j = 0;j < num; j++){ scanf("%d",&temp); t[i].push_back(temp); } } for(int i = 1;i <= n; i++) scanf("%d%d",&cor[i].x,&cor[i].y); m = 0; for(int i = 1;i <= n; i++){ for(int j = i + 1;j <= n; j++){ edge[m].x = i; edge[m].y = j; edge[m++].dis = distances(cor[i],cor[j]);//计算每一条边的长度 } } sort(edge,edge+m,cmp); //kruskal特有 solve(); } return 0; }
时间: 2024-10-12 07:57:43