bzoj1854 [Scoi2010]遊戲 二分圖匹配 並查集
Description
lxhgww最近迷上了一款遊戲,在遊戲裡,他擁有很多的裝備,每種裝備都有2個屬性,這些屬性的值用[1,10000]之間的數表示。當他使用某種裝備時,他只能使用該裝備的某一個屬性。並且每種裝備最多隻能使用一次。 遊戲進行到最後,lxhgww遇到了終極boss,這個終極boss很奇怪,攻擊他的裝備所使用的屬性值必須從1開始連續遞增地攻擊,才能對boss產生傷害。也就是說一開始的時候,lxhgww只能使用某個屬性值為1的裝備攻擊boss,然後只能使用某個屬性值為2的裝備攻擊boss,然後只能使用某個屬性值為3的裝備攻擊boss……以此類推。 現在lxhgww想知道他最多能連續攻擊boss多少次?
對於30%的資料,保證N < =1000
對於100%的資料,保證N < =1000000
Solution
原來去年做過的單殺lyk可以這樣做(不太記得了)
如果沒有相差為1和從1開始的限制,直接連(ai,i)和(bi,i)求二分圖最大匹配。容易發現順序無關,只要不同即可
具體到這題可以考慮從1開始列舉看是否能找到對應點
有一個trick就是在匈牙利dfs的時候不需要每次清空vis陣列,直接用時間戳標記會快很多
另一種做法參考自黃學長,對於一個武器看成一條邊(a,b)
若一個連通塊有n個點n-1條邊(一棵樹)則一定有一個點不能被取到
若一個連通塊有n個點至少n條邊,則任意一個點都能被取到
顯然我們讓一個連通塊中最大的點不能被取是最優的。合併的時候記錄一下,求答案的時候掃一遍即可
但是這樣做是有問題的,即一個有自環的點連在了樹上(畫圖腦補一下)的時候會錯,那麼離線所有的武器然後強行把ab相同的武器排在後面
Code
匈牙利做法
#include <stdio.h>
#include <string.h>
#define rep(i,st,ed) for (int i=st;i<=ed;++i)
#define fill(x,t) memset(x,t,sizeof(x))
#define max(x,y) ((x)>(y)?(x):(y))
const int N=1000005;
const int E=2000005;
struct edge{int y,next;}e[E];
int link[N],ls[N],edCnt=0;
int vis[N];
int read() {
int x=0,v=1; char ch=getchar();
for (;ch<'0'||ch>'9';v=(ch=='-')?(-1):(v),ch=getchar());
for (;ch<='9'&&ch>='0';x=x*10+ch-'0',ch=getchar());
return x*v;
}
void addEdge(int x,int y) {e[++edCnt]=(edge){y,ls[x]}; ls[x]=edCnt;}
int find(int now,int id) {
for (int i=ls[now];i;i=e[i].next) {
if (vis[e[i].y]==id) continue;
vis[e[i].y]=id;
if (!link[e[i].y]||find(link[e[i].y],id)) {
link[e[i].y]=now;
return 1;
}
}
return 0;
}
int main(void) {
freopen("data.in","r",stdin);
freopen("std.out","w",stdout);
int n=read(),mx=0;
rep(i,1,n) {
int x=read(),y=read();
mx=max(mx,x); mx=max(mx,y);
addEdge(x,i);
addEdge(y,i);
}
int ans=0;
rep(i,1,mx) {
if (find(i,i)) ans++;
else break;
}
printf("%d\n", ans);
return 0;
}
並查集做法
#include <stdio.h>
#include <string.h>
#include <algorithm>
#define rep(i,st,ed) for (int i=st;i<=ed;++i)
#define fill(x,t) memset(x,t,sizeof(x))
#define max(x,y) ((x)>(y)?(x):(y))
using std:: swap;
const int N=1000005;
int rank[N],fa[N],vis[N],x[N],y[N];
int read() {
int x=0,v=1; char ch=getchar();
for (;ch<'0'||ch>'9';v=(ch=='-')?(-1):(v),ch=getchar());
for (;ch<='9'&&ch>='0';x=x*10+ch-'0',ch=getchar());
return x*v;
}
int get_father(int now) {return (!fa[now])?(now):(fa[now]=get_father(fa[now]));}
void merge(int x,int y) {
x=get_father(x); y=get_father(y);
if (x>y) swap(x,y); vis[x]=1;
if (x!=y) fa[x]=y;
}
bool cmp(int a,int b) {return x[a]!=y[a]&&x[b]==y[b];}
int main(void) {
int n=read(),mx=0;
rep(i,1,n) {
x[i]=read(),y[i]=read();
rank[i]=i;
}
std:: sort(rank+1,rank+n+1,cmp);
rep(ti,1,n) {
int i=rank[ti];
mx=max(mx,x[i]); mx=max(mx,y[i]);
merge(x[i],y[i]);
}
int ans;
rep(i,1,mx+1) if (!vis[i]) {
ans=i-1;
break;
}
printf("%d\n", ans);
}
相關推薦
bzoj1854 [Scoi2010]遊戲 二分圖匹配 並查集
Description lxhgww最近迷上了一款遊戲,在遊戲裡,他擁有很多的裝備,每種裝備都有2個屬性,這些屬性的值用[1,10000]之間的數表示。當他使用某種裝備時,他只能使用該裝備的某一個屬性。並且每種裝備最多隻能使用一次。 遊戲進行到最後,lxh
BZOJ 1854: [Scoi2010]遊戲 二分圖匹配
lxhgww最近迷上了一款遊戲,在遊戲裡,他擁有很多的裝備,每種裝備都有2個屬性,這些屬性的值用[1,10000]之間的數表示。當他使用某種裝備時,他只能使用該裝備的某一個屬性。並且每種裝備最多隻能使用一次。 遊戲進行到最後,lxhgww遇到了終極boss,這個終極boss很奇怪,攻擊他的裝備所使用的屬性值
【bzoj 1854】[Scoi2010]遊戲 二分圖匹配
http://blog.csdn.net/pbihao/article/details/52835849 額,感覺像是一道題改一下就好了 #include<cstdio> #inclu
Codeforces 776D.The Door Problem (dfs二分圖判定 / 並查集)
二分圖染色 space find inline lin rem amp 屬於 兩個 題目鏈接: http://codeforces.com/problemset/problem/776/D 題意: n扇門,m個開關(n,m<=1e5),每個開關控制若幹個門,反轉開關門
BZOJ 4025 二分圖 分治+並查集
題目大意:給定一張n個點的圖,有m條邊,T個時間段,每條邊只存在於(st,ed]這些時間段,求每個時間段內這個圖是否是二分圖 分治並查集大法好 定義Solve(x,y,E)為當前處理的區間為[x,y],E為所有存在時間為[x,y]的子集的邊的集合 那麼對於
BZOJ 1854 SCOI2010 遊戲 二分圖最大匹配/並查集
題目大意:給定n個武器,每個武器有兩個屬性,只能使用其中一個,要求選擇一些武器 可以造成形如1 2 3 4的傷害 求最大傷害 題目大意我沒寫明白還是去看原題把QAQ 做法1: 同 1191 每個武器向兩個屬性連邊 然後從1~10000列舉屬性 跑二分圖最大匹配 無法匹配則輸
[luogu1640 SCOI2010]連續攻擊遊戲 (二分圖匹配)
() oss ring ems put printf class names 表示 [傳送門] (https://www.luogu.org/problemnew/show/P1640) Description lxhgww最近迷上了一款遊戲,在遊戲裏,他擁有很多的裝備,每
bzoj 1854: [Scoi2010]遊戲(二分圖的最大匹配)
1854: [Scoi2010]遊戲 Time Limit: 5 Sec Memory Limit: 162 MBSubmit: 3695 Solved: 1405 [Submit][Status][Discuss] Description lxhgww最近迷上了
[bzoj1059] [ZJOI2007] 矩陣遊戲 (二分圖匹配)
output efi 一個 否則 == 不變 答案 fin ostream 小Q是一個非常聰明的孩子,除了國際象棋,他還很喜歡玩一個電腦益智遊戲——矩陣遊戲。矩陣遊戲在一個N *N黑白方陣進行(如同國際象棋一般,只是顏色是隨意的)。每次可以對該矩陣進行兩種操作:行交換操作:
bzoj1059: [ZJOI2007]矩陣遊戲(二分圖匹配)
AI .com str php print 組成 line ems set 1059: [ZJOI2007]矩陣遊戲 題目:傳送門 題解: 為了趕上蘇大佬的光速的腳步...刷了題水題,不過蘇大佬好像一早就搞定了,所以也沒有什麽關系了對吧! 其實說水題的
BZOJ 1059 矩陣遊戲 二分圖匹配
不可 false 外掛 space 象棋 對角線 sizeof 決定 blank 題目鏈接: https://www.lydsy.com/JudgeOnline/problem.php?id=1059 題目大意: 小Q是一個非常聰明的孩子,除了國際象棋,他還很喜歡玩一個電腦
洛谷P1640 連續攻擊遊戲+二分圖匹配
本題是個二分圖匹配問題。首先我們來複習一下匈牙利演算法:用臨接矩陣寫的匈牙利:Code:(洛谷P3386) #include<iostream> #include<algorithm> #include<cstdio> #include<cstring>
BZOJ [ZJOI2007]矩陣遊戲(二分圖匹配)
1059: [ZJOI2007]矩陣遊戲 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 6390 Solved: 3133[Submit][Status][Discus
1059: [ZJOI2007]矩陣遊戲 二分圖匹配
1059: [ZJOI2007]矩陣遊戲 二分圖匹配 2016年11月14日 11:42:46 閱讀數:136 1059: [ZJOI2007]矩陣遊戲 Time Limit: 10 Sec Memory Limit: 16
$bzoj1059-ZJOI2007$矩陣遊戲 二分圖匹配
交換 顏色 dfs int mat 子圖 關系 象棋 algo 題面描述 小\(Q\)是一個非常聰明的孩子,除了國際象棋,他還很喜歡玩一個電腦益智遊戲——矩陣遊戲。矩陣遊戲在一個\(N*N\)黑白方陣進行(如同國際象棋一般,只是顏色是隨意的)。每次可以對該矩陣進行兩種操
51nod1307(暴力樹剖/二分&dfs/並查集)
href 存在 stdio.h cto pda long void 最大 amp 題目鏈接: http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1307 題意: 中文題誒~ 思路: 解法1:暴
[BZOJ3237][AHOI2013]連通圖(分治並查集)
break freopen spa width eight line sca rip urn 3237: [Ahoi2013]連通圖 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 1736 Solved: 655[S
【hiho】14 無間道之並查集【圖論--並查集】
const lse string turn problem scan -c for sca 傳送門:無間道之並查集 分析 並查集的分析可以看上面的傳送門,寫的挺好的了。 其實在我看來並查集就是一種方便的維護集合的一種技巧,提出了代表元素這一概念。 My AC Code #i
Newcoder 39 D.加邊的無向圖(並查集)
Description 給你一個 n n n 個點,
HDU 6350 2018HDU多校賽 第五場 Always Online(圖論 + 並查集 + 組合計數)
大致題意:給你一個仙人掌圖,讓你計算:。 根據去年多校賽某一道題的經驗,很多仙人掌圖的問題,其實可以轉化為樹的問題。所以我們同樣考慮,如果這是一棵樹的話如何去做。注意到表示式裡面的flow(i,j)表示從i到j的最小割或最大流,而在樹上的最小