SPOJ839 最優標號

2022-05-27 18:03:10 字數 2039 閱讀 2475

給你一張無向圖g(v,e)。每個頂點都有乙個標號,它是乙個[0,2^31-1]內的整數。不同的頂點可能會有相同的標號。

對每條邊(u,v),我們定義其費用cost(u,v)為u的標號與v的標號的異或值。

現在我們知道一些頂點的標號。你需要確定餘下頂點的標號使得所有邊的費用和盡可能小。

輸入檔案的第一行有兩個整數n,m(1<=n<=500,0<=m<=3000),n是圖的點數,m是圖的邊數。

接下來有m行,每行有兩個整數u,v,代表一條連線u,v的邊。

接下來有乙個整數k,代表已知標號的頂點個數。接下來的k行每行有兩個整數u,p,代表點u的標號是p。假定這些u不會重複。

輸出一行乙個整數,即最小的費用和。

【分析】

由題目敘述中,我們可以很容易看到,對於每個頂點的標號數的每個二進位制位上來說,它與前後該數的其他二進位制位是完全沒有任何聯絡的,所以我們不妨把每個數的二進位制位拆開來**,然後再求每個圖的最小割就可以了。

在建圖的時候,要注意的是,需要把二進位制位上為1的和二進位制位上為0的分開連線到源點和匯點。

最後,注意重邊!

1 #include 2 #include 3 #include 4 #include 5 #include 6 #include 7

const

int maxn=510;8

const

int maxm=3010;9

const

int inf=10000*10000;10

using

namespace

std;

11struct

liu12

15}maps[maxn][maxn];

16int

shu[maxn],map[maxn][maxn];

17int

bh[maxn],path[maxn],dist[maxn];

1819

intn,m,k;

20long

long solve(int

times);

21void make_maps(int

times);

22bool

bfs();

23int dfs(int u,int

low);

2425

intmain()

2639 scanf("

%d",&k);

40for (i=1;i<=k;i++)

4146

47long

long ans=0;48

//注意求解次數

49for (i=0;i<=31;i++) ans+=solve(i);//

求解最大流

50 printf("

%lld

",ans);

51return0;

52}53//

求解函式

54long

long solve(int

times)

5565

//printf("%d\n",flow);

66return (long

long)flow<

68//

構圖 69

void make_maps(int

times)

7081

else 82}

83for (i=1;i<=n;i++)

84for (j=1;j<=n;j++)

8590

return;91

}92bool bfs()//

bfs構建層次網路

93110

}111

} 112

return (dist[n+1]!=-1

);113

}114

int dfs(int v,int low)//

增廣 115

131}

132}

133return

flow;

134 }

view code

spoj 694 705 字尾陣列

每個子串一定是某個字尾的字首,那麼原問題等價於求所有字尾之間的不相同的字首的個數。如果所有的字尾按照 suffix sa 1 suffix sa 2 suffix sa 3 suffix sa n 的順序計算,不難發現,對於每一次新加進來的字尾 suffix sa k 它將產生 n sa k 1 個...

Spoj 1433 數字問題

題目大意 將 1 n 1 n 15 10 寫在紙上,然後在相鄰的數字間交替插入 和 求最後的 結果。例如當 n 為 12 時,答案為 1 2 3 4 5 6 7 8 9 1 0 1 1 1 2 5 解法分析 這是一道稍微複雜一點的數字計數問題。根據上述原則,我們首先探查數字確定,所有數字自由的情況。...

SPOJ 227 樹狀陣列

題意 給定乙個排列和陣列b i 表示i前面比a i 小的點的個數,求a i n的乙個排列 solution 維護乙個c陣列,表示c 從右向左對每個b i 找到最小的j 使c j b i 則a i j 如何維護c 樹狀陣列 如何查詢j 二分 include include include includ...