日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【2019牛客暑期多校训练营(第二场) - D】Kth Minimum Clique(bfs,tricks)

發布時間:2023/12/10 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【2019牛客暑期多校训练营(第二场) - D】Kth Minimum Clique(bfs,tricks) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題干:

鏈接:https://ac.nowcoder.com/acm/contest/882/D
來源:牛客網
?

Given a vertex-weighted graph with N vertices, find out the K-th minimum weighted clique.

A subset of vertices of an undirected graph is called clique if and only if every two distinct vertices in the subset are adjacent. The weight of a clique is the summation of the weight of vertices in it.

輸入描述:

The first line of input contains two space-separated integers N, K. The second line of input contains N space-separated integers wiw_iwi? representing the weight of each vertex. Following N lines each contains N characters eije_{ij}eij?. There's an edge between vertex i and vertex j if and only if eij="1"e_{ij} =\texttt{"1"}eij?="1".1≤N≤1001 \leq N \leq 1001≤N≤100 1≤K≤1061 \leq K \leq 10^61≤K≤106 0≤wi≤1090 \leq w_i \leq 10^90≤wi?≤109 eij∈"01"e_{ij} \in \texttt{"01"}eij?∈"01" eii="0"e_{ii} = \texttt{"0"}eii?="0" eij=ejie_{ij} = e_{ji}eij?=eji?

輸出描述:

Output one line containing an integer representing the answer. If there's less than K cliques, output "-1"\texttt{"-1"}"-1".

示例1

輸入

復制

2 3 1 2 01 10

輸出

復制

2

說明

An empty set is considered as a clique.

題目大意:

定義一個團的權值就是團中點的權值和。給定一個n個點的圖(n<=100),求第K大的團。(K<=1e6)

解題報告:

其實是考慮到:因為是個團,而不是連通圖,所以會有一些性質。

其實看到這題,第一反應肯定是2^100枚舉,這樣肯定是沒錯的。考慮時間耗費在哪里了呢?因為有一些根本不是團的情況也被你搜索到了。所以考慮優化:直接在團的基礎上進行搜索枚舉,但是還有個問題,那就是他萬一是個完全圖,那還是2^100次方呀。

但是還好,這題告訴你了K<=1e6,所以肯定要在這上面做點文章。還是按照剛剛的想法的話肯定是搜索所有的團,然后排個序輸出第k個值,但是如果是完全圖的話,那團的大小就有2^100個,肯定不能搜索完所有的團,那么考慮,K既然是已知的了,可不可以只搜索到前K大?所以思路就是優先隊列的bfs,直接搜到K個就停止,這樣總復雜度就是nlogn了。

注意這題有個小坑,那就是不bfs的過程中,加入新節點的時候需要去重,不然肯定能WA啊、、為了處理這個事情有好多種辦法,可以直接HASH,也可以用代碼中的方法:記錄最后個有效節點是哪個節點,下次直接在這個往后面搜索。原理是因為你bfs每一層的時候都保證了只加入一個節點,所以你在此時前面的點都判斷過了,所以不需要再加入了。但是你如果不這樣判斷一波的話,肯定就會有重復的團被算了多次。

貼一個題解:

我們發現我們很難直接高效的算出一張圖的第k小團的權值。因此,我們考慮將這個問題轉化一下。我們發現,因為權值都是正數,因此如果在一個已知的團上能夠再增加一個新結點形成團,那么新的團的權值必定增加。因此,我們如果從空集不斷往上去增加新的結點構造成團,那么在這個過程中,權值一定是不斷增加的。因此我們只需要從小到大拓展團,并將當前的團的權值丟進一個優先隊列里進行維護,最后不斷獲取到第k小的權值即可。至此,我們需要考慮如何能夠高效的在一個團上增加新的結點。我們還可以考慮每次只加當前點后面的點,避免重復。

AC代碼:

#include<cstdio> #include<iostream> #include<algorithm> #include<queue> #include<map> #include<vector> #include<bitset> #include<set> #include<string> #include<cmath> #include<cstring> #define FF first #define SS second #define ll long long #define pb push_back #define pm make_pair using namespace std; typedef pair<int,int> PII; const int MAX = 100 + 5; struct Node {bitset<105> bs;ll w;int last;Node(){}Node(bitset<105> bs,ll w,int last):bs(bs),w(w),last(last){}bool operator<(const Node b)const {return w > b.w;} }; bitset<105> a[MAX]; int n,k,val[MAX]; ll bfs() {priority_queue<Node> pq;bitset<105> bb(0);k--;pq.push(Node(bb,0,0));while(pq.size()) {Node cur = pq.top();pq.pop();if(k == 0) return cur.w;k--;for(int i = cur.last+1; i<=n; i++) {if(cur.bs[i])continue;//==1????if((cur.bs & a[i]) == cur.bs) {cur.bs[i] = 1;pq.push(Node(cur.bs,cur.w + val[i],i));cur.bs[i] = 0;}} }return -1; } int main() {cin>>n>>k;for(int i = 1; i<=n; i++) cin>>val[i];for(int x,i = 1; i<=n; i++) {for(int j = 1; j<=n; j++) {scanf("%1d",&x);if(x == 1) a[i][j]=1;}}ll ans = bfs();printf("%lld\n",ans);return 0 ; }

錯誤代碼:

錯誤原因就是因為剛開始忘記去重了。

#include<cstdio> #include<iostream> #include<algorithm> #include<queue> #include<map> #include<vector> #include<bitset> #include<set> #include<string> #include<cmath> #include<cstring> #define FF first #define SS second #define ll long long #define pb push_back #define pm make_pair using namespace std; typedef pair<int,int> PII; const int MAX = 100 + 5; struct Node {bitset<105> bs;ll w;Node(){}Node(bitset<105> bs,ll w):bs(bs),w(w){}bool operator<(const Node b)const {return w > b.w;} }; bitset<105> a[MAX]; int n,k,val[MAX]; ll bfs() {priority_queue<Node> pq;bitset<105> bb(0);k--;pq.push(Node(bb,0));while(pq.size()) {Node cur = pq.top();pq.pop();if(k == 0) return cur.w;k--;for(int i = 1; i<=n; i++) {if(cur.bs[i]) continue;//==1????if((cur.bs & a[i]) == cur.bs) {cur.bs[i] = 1;pq.push(Node(cur.bs,cur.w + val[i]));cur.bs[i] = 0;}}}return -1; } int main() {cin>>n>>k;for(int i = 1; i<=n; i++) cin>>val[i];for(int x,i = 1; i<=n; i++) {for(int j = 1; j<=n; j++) {scanf("%1d",&x);if(x == 1) a[i][j]=1;}}ll ans = bfs();printf("%lld\n",ans);return 0 ; }

?

總結

以上是生活随笔為你收集整理的【2019牛客暑期多校训练营(第二场) - D】Kth Minimum Clique(bfs,tricks)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。