[CF1515F]Phoenix and Earthquake

Posted Tan_tan_tann

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[CF1515F]Phoenix and Earthquake相关的知识,希望对你有一定的参考价值。

Phoenix and Earthquake

题解

挺水的一道题。

首先我们要想明白如何判断一个图是否能行。
首先,如果不是联通图或者 ∑ i = 1 n a i < ( n − 1 ) x \\sum_{i=1}^{n}a_{i}< (n-1)x i=1nai<(n1)x是肯定不行的,因为它合并都合并不了 n − 1 n-1 n1条边。
否则,它是一定能行的。因为这样必定有一条边的两端和是大于 x x x,那么这条边就一定可以被合并掉。然后,我们得到的是一个 n − 1 n-1 n1个点,且 ∑ i = 1 n a i ⩾ ( n − 2 ) x \\sum_{i=1}^{n}a_{i}\\geqslant (n-2)x i=1nai(n2)x的图,这个图依旧可以重复以下过程。

证明了可行性,接下来我们操作呢?
首先,如果有一个权值不小于 x x x的点,我们可以直接将它与其它点合并,它与任意一个点合并都是可行的。
否则我们可以证明现当每个点都小于 x x x时,每一条边的和都是不小于 x x x的。
如果有一条边满足的 a u + a v < x a_{u}+a_{v}< x au+av<x,则其它 n − 2 n-2 n2个点都取 x − 1 x-1 x1,总和也达不到 ( n − 1 ) x (n-1)x (n1)x,也就是不满足我们最开始的条件,这当然是不可能的。
所以这样我们只需要随便合并一条边就可以了。
具体实现过程中,我们只需要每次对权值最大的点找一条边合并即可。

时间复杂度 O ( m l o g   n ) O\\left(mlog\\,n\\right) O(mlogn)

源码

#include<bits/stdc++.h>
using namespace std;
#define MAXN 300005
#define lowbit(x) (x&-x)
#define reg register
#define mp make_pair
#define fir first
#define sec second
typedef long long LL;
typedef unsigned long long uLL;
typedef unsigned int uint;
const int INF=0x7f7f7f7f;
const int jzm=233;
const int mo=998244353;
const double Pi=acos(-1.0);
typedef pair<int,int> pii;
const double PI=acos(-1.0);
template<typename _T>
_T Fabs(_T x){return x<0?-x:x;}
template<typename _T>
void read(_T &x){
	_T f=1;x=0;char s=getchar();
	while(s>'9'||s<'0'){if(s=='-')f=-1;s=getchar();}
	while('0'<=s&&s<='9'){x=(x<<3)+(x<<1)+(s^48);s=getchar();}
	x*=f;
}
int n,m,head[MAXN],tot,fa[MAXN],last[MAXN];LL val[MAXN],sum,x;
struct edge{int to,nxt;}e[MAXN<<1];
void addEdge(int u,int v){e[++tot]=(edge){v,head[u]};head[u]=tot;if(!last[u])last[u]=tot;}
void makeSet(int x){for(int i=1;i<=x;i++)fa[i]=i;}
int findSet(int x){return x==fa[x]?x:fa[x]=findSet(fa[x]);}
void unionSet(int a,int b){int u=findSet(a),v=findSet(b);if(u!=v)fa[u]=v;}
struct ming{LL val;int id;friend bool operator < (const ming &x,const ming &y){return x.val<y.val;}};
priority_queue<ming> q;
int main(){
	read(n);read(m);read(x);makeSet(n);
	for(int i=1;i<=n;i++)read(val[i]),sum+=val[i];
	for(int i=1,u,v;i<=m;i++)read(u),read(v),addEdge(u,v),addEdge(v,u);
	if(sum<1ll*(n-1)*x){puts("NO");return 0;}puts("YES");
	for(int i=1;i<=n;i++)q.push((ming){val[i],i});sum=0;
	while(!q.empty()&&sum<n-1){
		int t=q.top().id;q.pop();if(t!=findSet(t))continue;
		//printf("match %d\\n",t);
		for(int i=head[t];i;i=e[i].nxt){
			int v=findSet(e[i].to);head[t]=e[i].nxt;if(t==v)continue;
			val[t]=val[t]+val[v]-x;val[v]=0;fa[v]=t;q.push((ming){val[t],t});
			printf("%d\\n",(i+1)/2);(i==last[t]?head[t]:e[last[t]].nxt)=head[v];last[t]=last[v];sum++;break;
		}
	}
	puts("");
	return 0;
}
 

谢谢!!!

以上是关于[CF1515F]Phoenix and Earthquake的主要内容,如果未能解决你的问题,请参考以下文章

CF1348E Phoenix and Berries(dp)

[CF1348D] Phoenix and Science - 贪心

[CF1348D] Phoenix and Science - 贪心

CF 1348F Phoenix and Memory

CF 1348F Phoenix and Memory

[CF1515G]Phoenix and Odometers