【BZOJ3714】【PA2014】Kuglarz(最小生成樹)

Description

魔術師的桌子上有n個杯子排成一行,編號爲1,2,…,n,其中某些杯子底下藏有一個小球,如果你準確地猜出是哪些杯子,你就可以獲得獎品。花費c_ij元,魔術師就會告訴你杯子i,i+1,…,j底下藏有球的總數的奇偶性。
採取最優的詢問策略,你至少需要花費多少元,才能保證猜出哪些杯子底下藏着球?

Input

第一行一個整數n(1<=n<=2000)。
第i+1行(1<=i<=n)有n+1-i個整數,表示每一種詢問所需的花費。其中c_ij(對區間[i,j]進行詢問的費用,1<=i<=j<=n,1<=c_ij<=10^9)爲第i+1行第j+1-i個數。

Output

輸出一個整數,表示最少花費。

Sample Input

5

1 2 3 4 5

4 3 2 1

3 4 5

2 1

5

Sample Output

7

題解:
沒有思路的可以先去看一下小胖的奇偶這道題。
知道了第x~y個杯子的奇偶性,就相當於知道了x和x-1之間的縫到y和y+1之間的縫的奇偶性,知道了縫a到縫b的奇偶性和縫b到縫c的奇偶性,我們就知道了縫a到縫c的奇偶性。要知道所有杯子底下有沒有球,我們就要知道每個杯子左右兩端的縫之間的奇偶性,也就相當於要知道任意兩個縫之間的奇偶性,所以這就是一道花式最小生成樹問題,知道奇偶性相當於連一條邊,整個圖聯通了就都能知道了。

代碼如下:

#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<math.h>
#define ll long long
#define N 2005
#define inf 0x7f7f7f7f
using namespace std;
int n,x; 
int hd[N],tot,fa[N];
struct nod
{
    int x,y,v;
    nod(){}
    nod(int a,int b,int c):x(a),y(b),v(c){}
    inline bool operator<(const nod& rhs) const {return v<rhs.v;}
}e[N*N];
int find(int x)
{
    if(fa[x]==x) return x;
    return fa[x]=find(fa[x]);
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n+1;i++) fa[i]=i;
    for(int i=1;i<=n;i++)
    for(int j=i;j<=n;j++)
    {
        scanf("%d",&x);
        e[++tot]=nod(i,j+1,x);
    }
    sort(e+1,e+tot+1);
    ll ans=0,t=0;  
    for(int i=1;i<=tot;i++) 
    {  
        int fx=find(e[i].x),fy=find(e[i].y);  
        if(fx!=fy) 
        {  
            fa[fy]=fx;  
            ans+=e[i].v;  
            if(++t==n) break;  
        }  
    }  
    printf("%lld\n",ans);
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章