Doremy‘s Connecting Plan(cf 906 div2)

Doremy生活在一个由编号从1到n的n个城市组成的国家,第二个城市居住着ai人。它可以被建模为具有n节点的无向图。最初,图形中没有边。现在Doremy想要使图连通。

要做到这一点,她可以在i和j之间添加一条边,并且满足以下条件

Doremy‘s Connecting Plan(cf 906 div2)_第1张图片

其中S是当前在i或j的同一连通分量中的所有节点的集合,c是给定的常数。Doremy能把图连接起来吗?如果存在从i到j的路径,则两个节点(i,j)在同一连通分量中。如果图的所有节点都在同一个连接的组件中,则图是连接的。

多组输入 t(1≤t≤10^4)

输入 第一行输入  n, c (2≤n≤2*10^5, 1≤c≤10^6)

输出 可以输出 Yes 否则 No

输入样例  

7
4 10
0 20 15 10
2 1
1 1
5 1
0 1 0 4 199
5 2
1 1 3 1 1
5 5
5 6 1 10 2
5 1000000
1000000000000 1000000000000 1000000000000 1000000000000 1000000000000
3 1
0 0 2 

输出样例 

Yes
Yes
Yes
No
No
Yes
No 

思路: 

假设存在2个大于1的下标i,j 初始时它们满足

ai+aj>=i*j*c

证明 ai和aj至少存在一个点,可以和a1相连

反证法:

假设ai和aj都不能与a1相连

那么

ai+aj>=i*j*c

ai+a1

aj+a1

从而推出

2*a1+ai+aj<(i+j)*c

则 i*j*c<(i+j)*c

i*j<(i+j)

i

j

与i>2矛盾

所以优先取a1 与其他点相连

a1+aj>=1*j*c

则 a1>=j*c-aj

则 sum>=j*c-aj(即可 若不行 则 No 应该从小到大取弄 )

j*c-aj从小到大排序

如果 sum

#include
#include
using namespace std;
typedef long long ll;
const int N=2e5+10;
pairp[N];
ll a[N];
int main()
{
	int t;cin>>t;
	while(t--)
	{
		ll n,c;cin>>n>>c;
		
		for(int i=1;i<=n;i++) cin>>a[i];
		for(int i=2;i<=n;i++)
		{
			p[i].first=i*c-a[i];
			p[i].second=i;
		}
		sort(p+2,p+1+n);
		ll sum=a[1];
		int flag=1;

		for(int i=2;i<=n;i++)
		{
		    ll num=p[i].first,num1=p[i].second;
			if(sum

 

你可能感兴趣的:(cf,算法,cf)