时间限制(普通/Java) : 1000 MS/ 3000 MS 运行内存限制 : 65536 KByte
总提交 : 4 测试通过 : 2
比赛描述
oo吃饱了想跟饥饿的你玩一个游戏。你们面前的桌子上有n个碗排成一行,编号为1,2,…,n,其中某些碗底下藏有一个小球,如果你准确地猜出是哪些杯子,你就可以获得由oo赠送的零食。你也可以贿赂oo,花费c_ij元,oo就会告诉你碗i,i+1,…,j这一段里球的总数的奇偶性。 你很好奇oo都准备了哪些零食。如果你采取了最优的询问策略,你至少需要花费多少元,才能保证拿到oo的所有奖励?
输入
ToDo
第一行一个整数T(1<=T<=10)表示case的数量 对于每个case,第一行一个整数n(1<=n<=400),表示碗的数量。 下面n行,对于第i行,j从i开始。 比如 1 2 3 表示1-1花费1,1-2花费2,2-2花费3。 每行有n-i+1个整数,第i行第j个数表示询问i,i+1….j需要的花费。(1<=i<=j<=n,1<=c_ij<=10^9)
输出
每个case输出一个整数,表示最小花费
样例输入
1
5
1 2 3 4 5
4 3 2 1
3 4 5
2 1
样例输出
7
题解:样例和题目好像都有毛病…不过就是一个最小生成树,这样可以以最小的权值知道所有的信息
用的是K树,即用并查集实现的最小边加边法
/* ID: oodt PROG: LANG:C++ */ #include<iostream> #include<algorithm> #include<cstdio> #include<cmath> #include<string> #include<cstring> #include<cassert> #include<map> #include<vector> #include<queue> #include<stack> #include<set> using namespace std; #define rep(i,a,n) for (int i=a;i<n;i++) #define per(i,a,n) for (int i=n-1;i>=a;i--) #define pb push_back #define mp make_pair #define all(x) (x).begin(),(x).end() #define fi first #define se second #define SZ(x) ((int)(x).size()) typedef vector<int> VI; typedef long long ll; typedef pair<int,int> PII; const ll mod=1000000007; ll powmod(ll a,ll b) {ll res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;} ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;} const int maxx=2005; const int INF = 0x3f3f3f3f; int n,m,k; int c[maxx][maxx]; int vis[maxx]; int ans = 0,cnt = 0,pos = 0; int l = 0,r = 0; const int MAXN = 2010; const int MAXM = 4000200; int F[MAXN]; struct Edge { int u,v,w; }edge[MAXM]; int tol; void addedge(int u,int v,int w) { edge[tol].u = u; edge[tol].v = v; edge[tol++].w = w; } bool cmp(Edge a,Edge b) { return a.w<b.w; } int find(int x) { if(F[x] == -1) return x; else return F[x] = find(F[x]); } ll kruskal(int n) { memset(F,-1,sizeof(F)); sort(edge,edge+tol,cmp); int cnt = 0; ll ans = 0; for(int i = 0; i < tol; i++) { int u = edge[i].u; int v = edge[i].v; int w = edge[i].w; int t1 = find(u); int t2 = find(v); if(t1 != t2) { ans += w; F[t1] = t2; cnt ++; } if(cnt == n-1) break; } return ans; } int main() { int T; scanf("%d",&T); while(T--) { tol = 0; scanf("%d",&n); rep(i,0,n){ rep(j,i+1,n+1){ scanf("%d",&c[i][j]); addedge(i,j,c[i][j]); } } ll ans = kruskal(n+1); printf("%I64\n",ans); } return 0; }