蓝桥杯 国王的烦恼 逆向并查集建树
2017-05-26 23:13
260 查看
题目链接
思路:
按照题目的要求的话我们有一个特别简单粗暴的做法,那就是对于每次不能用一条边,我们就对剩下的边求一下连通分量,但是m那么大肯定T了,对此我们有一个简单的做法那就是从后往前逆向考虑.
我们将所有的边按照所能使用的天数从大到小排序,然后用并查集维护一下,每判断一条边时就需要判断这两个点是否已经连通,如果连通就说明不需要抱怨,否则就要抱怨.另外注意需要记录天数是否一样,同一天的也只记录一次.
这里因为我们从后往前建树,对于要添加的这条边我们先判断两点是否连通就可以判断出如果这条边删除了对以后是否有影响,如果连通则没影响否则有影响
#include<bits/stdc++.h>
#define Ri(a) scanf("%d", &a)
#define Rl(a) scanf("%lld", &a)
#define Rf(a) scanf("%lf", &a)
#define Rs(a) scanf("%s", a)
#define Pi(a) printf("%d\n", (a))
#define Pf(a) printf("%lf\n", (a))
#define Pl(a) printf("%lld\n", (a))
#define Ps(a) printf("%s\n", (a))
#define W(a) while(a--)
#define CLR(a, b) memset(a, (b), sizeof(a))
#define MOD 1000000007
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
int pre[maxn];
int n,m;
struct node
{
int u,v,t;
}q[maxn];
int cmp(node x,node y)
{
return x.t>y.t;
}
void init()
{
for(int i=1;i<maxn;i++)
{
pre[i]=i;
}
return ;
}
int find(int x)
{
if(x==pre[x])
return x;
return pre[x]=find(pre[x]);
}
int join(int x,int y)
{
int f1=find(x);
int f2=find(y);
if(f1!=f2)
{
pre[f1]=f2;
return 1;
}
return 0;
}
int main()
{
Ri(n),Ri(m);
init();
for(int i=1;i<=m;i++)
{
Ri(q[i].u),Ri(q[i].v),Ri(q[i].t);
}
sort(q+1,q+1+m,cmp);
int cnt=0,pre=-1;
for(int i=1;i<=m;i++)
{
if(join(q[i].u,q[i].v))
{
if(pre!=q[i].t)
{
cnt++;
pre=q[i].t;
}
}
}
Pi(cnt);
return 0;
}
思路:
按照题目的要求的话我们有一个特别简单粗暴的做法,那就是对于每次不能用一条边,我们就对剩下的边求一下连通分量,但是m那么大肯定T了,对此我们有一个简单的做法那就是从后往前逆向考虑.
我们将所有的边按照所能使用的天数从大到小排序,然后用并查集维护一下,每判断一条边时就需要判断这两个点是否已经连通,如果连通就说明不需要抱怨,否则就要抱怨.另外注意需要记录天数是否一样,同一天的也只记录一次.
这里因为我们从后往前建树,对于要添加的这条边我们先判断两点是否连通就可以判断出如果这条边删除了对以后是否有影响,如果连通则没影响否则有影响
#include<bits/stdc++.h>
#define Ri(a) scanf("%d", &a)
#define Rl(a) scanf("%lld", &a)
#define Rf(a) scanf("%lf", &a)
#define Rs(a) scanf("%s", a)
#define Pi(a) printf("%d\n", (a))
#define Pf(a) printf("%lf\n", (a))
#define Pl(a) printf("%lld\n", (a))
#define Ps(a) printf("%s\n", (a))
#define W(a) while(a--)
#define CLR(a, b) memset(a, (b), sizeof(a))
#define MOD 1000000007
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
int pre[maxn];
int n,m;
struct node
{
int u,v,t;
}q[maxn];
int cmp(node x,node y)
{
return x.t>y.t;
}
void init()
{
for(int i=1;i<maxn;i++)
{
pre[i]=i;
}
return ;
}
int find(int x)
{
if(x==pre[x])
return x;
return pre[x]=find(pre[x]);
}
int join(int x,int y)
{
int f1=find(x);
int f2=find(y);
if(f1!=f2)
{
pre[f1]=f2;
return 1;
}
return 0;
}
int main()
{
Ri(n),Ri(m);
init();
for(int i=1;i<=m;i++)
{
Ri(q[i].u),Ri(q[i].v),Ri(q[i].t);
}
sort(q+1,q+1+m,cmp);
int cnt=0,pre=-1;
for(int i=1;i<=m;i++)
{
if(join(q[i].u,q[i].v))
{
if(pre!=q[i].t)
{
cnt++;
pre=q[i].t;
}
}
}
Pi(cnt);
return 0;
}
相关文章推荐
- 蓝桥杯--- 历届试题 国王的烦恼 (并查集)
- 蓝桥杯 国王的烦恼 反向并查集
- 蓝桥杯历届试题——国王的烦恼(并查集)
- 国王的烦恼蓝桥杯 并查集
- 蓝桥杯 国王的烦恼(排序+并查集)
- 蓝桥杯历届试题 国王的烦恼(思维并查集)
- (蓝桥杯)历届试题 国王的烦恼 (并查集)
- 蓝桥杯 历届试题 国王的烦恼(并查集)
- 蓝桥杯 国王的烦恼(并查集)
- 蓝桥杯 历届试题 国王的烦恼
- 蓝桥杯 国王的烦恼
- 国王的烦恼 蓝桥杯(最小生成树 kru)
- 并查集-国王的烦恼
- 历届试题 国王的烦恼 蓝桥杯
- [蓝桥杯][历届试题]国王的烦恼
- 历届试题 国王的烦恼 (蓝桥杯)
- 历届试题 国王的烦恼 (并查集)
- 蓝桥杯 历届试题 国王的烦恼
- 国王的烦恼 —— 并查集,贪心
- nyoj_925国王的烦恼(并查集最大生成树)