略這題是並查集的乙個變題,先按積怨值從大到小排序,然後乙個乙個看能否完全分開,遇到的第乙個不能分開的囚犯對(如果強行分開就必然有更高的積怨值出現)就是答案。
一開始想到的是按監獄數量弄個並查集,後來發現並不行,因為如果要分開一對囚犯,沒辦法決定誰一定住1號監獄,誰一定住2號監獄。後來試了下用囚犯數量弄並查集,發現也不行,因為沒有積怨的才能放乙個集合裡,比如1和2有積怨不在一起,3和4有積怨不在一起,那1和3,1和4等等就沒法確定,那把他們都放不同集合裡?不行,因為不在乙個集合的可能有積怨可能沒積怨。
讓後我就想當選取到i + 1對囚犯時,前i對囚犯必然也形成一張圖,這張圖可能不是連通的,換句話說,就是包含多個極大聯通子圖(囚犯小團體),小團體與小團體之間互相沒有積怨,因為程式已經選取到了i + 1對囚犯,所以這些小團體內部必然可以兩兩分開以致於沒有積怨。選取其中乙個小團體,如果這個極大聯通子圖沒有壞,那必然可以變形成如下形式:
也就是說,肯定可以一刀切。
如果有環,那促成環的這條線的兩端必分別屬於左右兩邊:
如果這個時候來了一條邊,它的兩個端點都在這張圖的一邊:
那這張圖必然怎麼切都切不開了。
也就是說,如果第i + 1對囚犯都屬於某乙個小團體的一邊,答案就出來了。
也就是說每名囚犯應該有2個狀態i和i',上面的圖應該是這樣:
於是並查集的長度應該為2n,前n個表示1~n,後n個表示1'~n'。
ps:**中並沒有判斷是否在都一邊而是直接判斷在不在乙個集合,這是因為是直接查詢的同一邊的點,就是沒有'的那邊,這樣直接判斷在不在乙個集合就可以了。
1 #include 2view codeusing
namespace
std;34
#define rep(i,n) for (int i = 0; i < (n); ++i)
5#define for(i,s,t) for (int i = (s); i <= (t); ++i)
6#define rfor(i,t,s) for (int i = (t); i >= (s); --i)
7#define foreach(i,c) for (__typeof(c.begin()) i = c.begin(); i != c.end(); ++i)
8#define rforeach(i,c) for (__typeof(c.rbegin()) i = c.rbegin(); i != c.rend(); ++i)910
#define pr(x) cout << #x << " = " << x << " "
11#define prln(x) cout << #x << " = " << x << endl
1213
#define all(x) x.begin(),x.end()
14#define ins(x) inserter(x,x.begin())
1516
#define ms0(a) memset(a,0,sizeof(a))
17#define msi(a) memset(a,inf,sizeof(a))
1819
#define pii pair20
#define piii pair,int>
21#define mp make_pair
22#define pb push_back
23#define fi first
24#define se second
2526 inline int
gc()
3334 inline int
ri()
4041 typedef long
long
ll;42
const
int maxn = 1e5 + 7;43
44struct
edge
48 edge(int x, int y, int
w) : x(x), y(y), w(w) {}
4950
bool
operator
< (const edge &x) const
53};
5455
intn, m, ans;
56edge e[maxn];
57int
f[maxn];
5859
int find(int
x) 63
64int
main()
73 sort(e+1, e+m+1
);74 for(i, 1, n<<1) f[i] =i;
7576 for(i, 1
, m)
84 f[x] = find(e[i].y +n);
85 f[y] = find(e[i].x +n);86}
8788 printf("
%d\n
", ans);
89return0;
90 }
洛谷 關押罪犯 NOIP2010提高組複賽
s 城現有兩座監獄,一共關押著n 名罪犯,編號分別為1 n。他們之間的關係自然也極不和諧。很多罪犯之間甚至積怨已久,如果客觀條件具備則隨時可能爆發衝突。我們用 怨氣值 乙個正整數值 來表示某兩名罪犯之間的仇恨程度,怨氣值越大,則這兩名罪犯之間的積怨越多。如果兩名怨氣值為c 的罪犯被關押在同一監獄,他...
NOIP 2010提高組題解
這是同機房一位巨佬在ak ioi之後發表的感言。為了學習他的這種精神 我太菜了,但我也想像他一樣ak ioi qaq 這篇題解就誕生了。戰車被馬拉著 直接模擬。注意入隊的時候打上標記,出隊的時候清楚標記,每次查詢的時候直接o 1 o 1 o 1 查詢標記即可。時間複雜度o n o n o n 一直在...
NOIP2010提高組 引水入城
這題。以前打的,很暴力的bfs include include using namespace std int a 502 502 ll 502 rr 502 data 300001 2 bool bz 502 502 int temp,n,m const int way 5 2 void bfs ...