NC16884 食物链
题目链接
关键点:
1、对于每个动物只有ABC三种可能,我们可以将三种可能情况都列出
2、如果两个为同类,那么就可以直接连接(A-A,B-B,C-C),为吃的关系(A-B,B-C,C-A)
3、判断是否有误,则看想反的情况是否有出现,比如对于同类的判断,如果(A-B||A-C)那么就为有误的判断,同理如果为吃,但是(A-A||A-C)那么就为有误的判断
4、对于吃与被吃,同类都是可以传递的关系,因此用并查集
完整代码
# include <bits/stdc++.h>
using namespace std;
int fa[50010*3];
int n, k, cnt;
int find(int x){
return (fa[x]==x)? x: fa[x] = find(fa[x]);
}
void merge(int x, int y)
{
fa[find(x)] = find(y);
}
int main()
{
cin>>n>>k;
for (int i=1; i<=n*3; i++)
fa[i] = i;
for (int i=1; i<=k; i++)
{
int d, x, y;
cin>>d>>x>>y;
if (x>n || y>n)
{
cnt++;
continue;
}
if (d==1)
{
if (find(x)==find(y+n)||find(x)==find(y+2*n))
cnt++;
else
{
merge(x, y);
merge(x+n, y+n);
merge(x+2*n, y+2*n);
}
}
else
{
if (find(x)==find(y)||find(x)==find(y+2*n))
cnt++;
else
{
merge(x, y+n);
merge(x+n, y+n*2);
merge(x+2*n, y);
}
}
}
cout<<cnt<<endl;
return 0;
}
NC51097 Parity game
题目链接
关键点:
1、同样的,对于一个区间的奇偶性,比如区间(i,j)我们可以分为(0,i-1),(i,j)中的奇偶性,如果(i,j)奇偶性为偶,那么说明(0,i-1),(i,j)奇偶性相同,如果(i,j)奇偶性为奇,那么说明(0,i-1),(i,j)奇偶性不同,因此我们可以采取和食物链同样的做法,将是奇和偶都算一次
2、对于如何维护前缀和,我们可以用undered_map来维护i-1和j,表示从开始到结束的奇偶性
完整代码
# include <bits/stdc++.h>
using namespace std;
unordered_map<int, int>fa;
int k, n;
int find(int x)
{
return (fa[x]==x)? x: fa[x] = find(fa[x]);
}
void merge(int x, int y)
{
fa[find(x)] = find(y);
}
int main()
{
cin>>n>>k;
int cnt = k;
n++;
for (int i=0; i<k; i++)
{
int x, y;
string s;
cin>>x>>y>>s;
if (!fa.count(y)) fa[y]=y, fa[y+n]=y+n;
if (!fa.count(x-1)) fa[x-1] = x-1, fa[x-1+n] = x-1+n;
if (s[0] == 'e')
{
if (find(x-1) == find(y+n)||find(x+n-1)==find(y))
{
cnt = i;
break;
}
else
{
merge(x-1, y);
merge(x+n-1, y+n);
}
}
else
{
if (find(x-1)==find(y)||find(x+n-1)==find(y+n))
{
cnt = i;
break;
}
else
{
merge(x-1, y+n);
merge(x+n-1, y);
}
}
}
cout<<cnt;
return 0;
}
NC235745 拆路
题目链接
关键点:
1、对于要拆除的路,我们可以在一开始就将其不要建成,然后将所有的操作倒着来,碰到拆除的操作就为连边操作
完整代码:
# include <bits/stdc++.h>
using namespace std;
const int N = 100000+10;
int n, m, q;
int fa[N];
int cnt[N];
map<int, int>mp;
typedef pair<int, int> P;
int r[N][3];
set<P>s;
char qu[N];
int ask[N];
int d[N][3];
stack<int>st;
int find(int x)
{
if (fa[x] == x)
return x;
else
return fa[x] = find(fa[x]);
}
void merge(int x, int y)
{
int f1 = find(x), f2 = find(y);
if (f1!=f2)
{
if (cnt[f1]>cnt[f2])
fa[f2] = f1;
else
fa[f1] = f2;
}
}
int main()
{
cin>>n>>m;
for (int i=1; i<=n; i++)
{
fa[i] = i;
cin>>cnt[i];
}
for (int i=1; i<=m; i++)
{
int x, y;
cin>>x>>y;
r[i][0] = x;
r[i][1] = y;
}
cin>>q;
for (int i=1; i<=q; i++)
{
char c;
cin>>c;
qu[i] = c;
if (c == 'Q')
{
int a;
cin>>a;
ask[i] = a;
}
else
{
int a, b;
cin>>a>>b;
s.insert(P{a, b});
s.insert(P{b, a});
d[i][0] = a;
d[i][1] = b;
}
}
for (int i=1; i<=m; i++)
{
if (s.find(P{r[i][0], r[i][1]})==s.end())
{
merge(r[i][0], r[i][1]);
}
}
for (int i=q; i>=1; i--)
{
if (qu[i]=='Q')
{
int x = ask[i];
st.push(cnt[find(x)]);
}
else
{
int x = d[i][0];
int y = d[i][1];
merge(x, y);
}
}
while (!st.empty())
{
cout<<st.top()<<endl;
st.pop();
}
return 0;
}