国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

codevs 1069 關押罪犯

2019-11-06 06:39:53
字體:
來源:轉載
供稿:網友

codevs 1069 關押罪犯

本來想著只需要用sort把這對犯人按怨氣值排序即可,然后從大到小把犯人放在不同的監獄里即可,后來才返現我忽視了一個重要問題,比如: a-b c-d ,接下來是b - c , b - d,就是c, d 倉庫的方法對后面是有影響的。現在就發現,這個問題我似乎又不知道怎么去思考好了。考慮圖形的環狀嗎?可是maxN = 20000。

看了題解,發現最好的方法是用并查集做(怎么自己就完全沒有想到這個算法呢?太嫩了啊- - ) 代碼:

#include<iostream> #include<algorithm> using namespace std; int fa[55555]; struct S { int a, b, c; friend inline bool Operator < (S a, S b) { return a.c > b.c; } } dat[100000]; int find(int x) { return fa[x] == x ? x : (fa[x] = find(fa[x])); } int main() { int n, m; cin >> n >> m; for (int i(0); i < m; ++i) cin >> dat[i].a >> dat[i].b >> dat[i].c; sort(dat, dat + m); for (int i(0); i < 2 * n; ++i) fa[i] = i; for (int i(0); i < m; ++i) { int fx(find(dat[i].a)), fy(find(dat[i].b)); if (fx == fy) { cout << dat[i].c << endl; return 0; } fa[fx] = find(dat[i].b + n); fa[fy] = find(dat[i].a + n); } cout << 0 << endl; return 0; }

解釋: 用并查集表示每個犯人之間的關系,在同一個集合中則說明兩人在同一個監獄,反之則不在同一個監獄。用類似于克魯斯卡爾的方法,先將邊排序,然后按照仇恨值的大小從大到小處理。對于每一組,先看兩個人能不能加入不同的集合, 如果可以,將兩人加入不同的集合,如果不可以,則輸出該組仇恨值。 用補集來表示兩個點不在一個集合中。如a和b’在同一個集合中,則a和b不在同一個集合中,不能把b直接加入另一個集合,因為會對后面的結果產生影響。 如,3和4不在同一個集合中,但是我們現在不知道究竟是3在第一個監獄還是4在第一個監獄,所以此時用3和4‘在同一個集合中來表示3和4不在同一個集合中。——轉載至http://blog.csdn.net/u013653310/article/details/46792373 自己的理解:(中午躺在床上半天終于想出來了),首先注意到有這條語句 int fx(find(dat[i].a)), fy(find(dat[i].b)); 說明fa[x]里面的x可能是(0 ~n,即本身),也可能是(x + n,即它的補集),所以先認清楚一個思維誤區,一個集合里面可能有(a+n , e+n,…),他們的聯通塊編號可能是某個數字,比如(e+n)。在同一個集合里面,所有的正常數字不能和里面的某個補集,比如a+n共存,也就說,所有數字不能和a放在同一個集合。那么a + n 和 e+n 都在的話,說明什么呢?我們可以這樣想:既然所有數字都不能和a 一起, 也不能和e一起,而且又只有2個監獄,那么a 只能和 e一起。在這份代碼中,只要某2個數字得到的聯通快編號一樣,說明它們在同一個集合中,就不能再在同一個監獄中,所以就是不合法的了。

終于想通了~總算懂了補集這個東西。每天進步一點點,萬歲!
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 修武县| 济宁市| 宜君县| 海丰县| 定南县| 绵竹市| 舟山市| 资中县| 武功县| 磐石市| 晋江市| 蒙阴县| 图们市| 台中市| 桂林市| 全南县| 恩施市| 泰来县| 河北省| 浦北县| 深泽县| 晋江市| 青川县| 永善县| 杭锦旗| 赤峰市| 宣城市| 丰城市| 浦东新区| 安阳县| 郸城县| 婺源县| 化德县| 博野县| 潼南县| 徐水县| 新民市| 新乐市| 安康市| 凤凰县| 饶平县|