7-1挂皮筋
zcx在51nod1307上扒的题
路径压缩把我压自闭了
结果rm不用优化就直接过???我服
#include<bits/stdc++.h>
#define Maxn 50000
using namespace std;
int fa[Maxn], r[Maxn];
bool flag = true;
void Init(int n){
for(int i = 0; i < n; i++) fa[i] = i;
}
void Find(int x, int w){
int f;
if(fa[x] != x){
int pre = fa[x];
Find(fa[x], w);
r[x] = min(r[pre], r[x] - w);
}
else r[x] -= w;
if(r[x] < 0) flag = false;
}
int main(){
int n, c, w, p, i;
cin >> n;
Init(n);
for(i = 0; i < n; i++){
cin >> c >> w >> p;
if(p == -1){
r[i] = c - w;
if(r[i] < 0) break;
}
else{
fa[i] = p;
r[i] = c;
Find(i, w);
if(!flag) break;
}
}
cout << i << endl;
return 0;
}
7-2
还是zcx在51nod1515上扒的题
我也不明白好好地并查集她为啥子要搞set
害得老子想压缩路径想到头秃
嘻m嘻m嘻p
搜到的题解都写得好jb长
真不明白明明50行就可以解决的问题为啥子非要写一百行
#include<bits/stdc++.h>
using namespace std;
static const int MAXN = 2e5 + 5;
int fa[MAXN], n, num;
map <int, int> table;
set<int> dif[MAXN];
void Init(){
for(int i = 0; i <= 2 * n; ++i) fa[i] = i;
}
int Find(int x){
return x == fa[x] ? x : fa[x] = Find(fa[x]);
}
int main(){
int x, y, p;
scanf("%d", &n);
Init();
while(n--){
scanf("%d%d%d", &x, &y, &p);
map<int, int>::iterator it = table.find(x);
x = (it == table.end()) ? (table[x] = num++) : table[x];
it = table.find(y);
y = (it == table.end()) ? (table[y] = num++) : table[y];
x = Find(x), y = Find(y);
if(p == 1){
if(x == y) puts("YES");
else{
set<int>::iterator it = dif[x].find(y);
if(it == dif[x].end()){
puts("YES");
if(dif[x].size() > dif[y].size()) swap(x, y);
fa[x] = y;
for(it = dif[x].begin(); it != dif[x].end(); it++){
dif[*it].insert(y);
dif[y].insert(*it);
}
}
else puts("NO");
}
}
else if(p == 0){
if(x == y) puts("NO");
else{
puts("YES");
dif[x].insert(y);
dif[y].insert(x);
}
}
}
return 0;
}
7-3终于正常模板题了 感动
#include<bits/stdc++.h>
using namespace std;
int fa[10005];
void Init(int n){
for(int i = 1; i <= n; i++) fa[i] = i;
}
int Find(int x){
return (x == fa[x]) ? x : fa[x] = Find(fa[x]);
}
int main() {
int n, q, opt, u, v;
scanf("%d%d", &n, &q);
Init(n);
while(q--){
scanf("%d%d%d", &opt, &u, &v);
int fu = Find(u), fv = Find(v);
if(opt == 1 && fu != fv) fa[fu] = fv;
else if(opt == 2) printf(fu == fv ? "Y\n" : "N\n");
}
return 0;
}
7-4
逆向并查集
输入样例:
8 13
0 1
1 6
6 5
5 0
0 6
1 2
2 3
3 4
4 5
7 1
7 2
7 6
3 6
5
1
6
3
5
7
输出样例:
1
1
1
2
3
#include<bits/stdc++.h>
using namespace std;
static const int INF = 1e9;
typedef pair<int, int> P;
P p[200010];
int vis[400010], fa[400010], n, m, k, cnt;
vector <int> q[400010];
vector <int> ans;
stack <int> S;
void Init(){
cnt = n - k;
for(int i = 0; i < n; i++){vis[i] = INF; fa[i] = i;}
while(!S.empty()) S.pop();
}
int Find(int x){
return (fa[x] == x) ? fa[x] : fa[x] = Find(fa[x]);
}
void merge(int x, int y){
int fx = Find(x), fy = Find(y);
if(fx != fy){fa[fx] = fy;cnt--;}
}
void print(){
for(int i = k; i >= 0; i--) printf("%d\n", ans[i]);
}
int main(){
int x, y;
scanf("%d%d", &n ,&m);
for(int i = 0; i < m; i++){
scanf("%d%d", &x, &y);
p[i].first = x; p[i].second = y;
}
scanf("%d", &k);
Init();
for(int i = 1; i <= k; i++){
scanf("%d", &x);
S.push(x);
vis[x] = i;
}
for(int i = 0; i < m ;i++){
x = p[i].first, y = p[i].second;
if(vis[x] < vis[y]) q[x].push_back(y);
else if(vis[y] < vis[x]) q[y].push_back(x);
else merge(x, y);
}
ans.push_back(cnt);
while(!S.empty()){
int u = S.top(); S.pop();
for(int i = 0; i < q[u].size(); i++) merge(u, q[u][i]);
ans.push_back(++cnt);
}
print();
return 0;
}
感觉我做得稍显麻烦 不知道有没有更简单的思路……