Tree,noi.ac模拟赛,Hall定理

正题

      题目链接点这里

      最小值最大,想到二分。

      二分一个答案k,我们把>=k的边全都删掉,留下的边把图分成了很多个联通块,这些联通块如果可以连到外面去的话,那么k就是满足条件的(因为走到外面去都要经过>=k的边啊

      那么就相当于一张二分图,左边(X集合)是1到n,右边(Y集合)有\sum_{i=1}^n x_i个节点,分别是x_1个1,x_2个2,...,x_n个n,第a个联通块内的节点连出去的边数都是一样的,\sum_{i=1}^n x_i-\sum_{i\in a}x_i(除去自己外其他联通块的xi的和

      那么我们现在跑一次二分图最大匹配就可以知道答案了!!

      判定二分图的算法除了匈牙利暴力和网络流你还会什么:Hall定理

      Hall定理给出了一个解决本问题一个很好的思路:如果X集合内任选a个点,所连的边都覆盖Y集合内>=a个点,那么这张二分图内一定有一个完全匹配。

      好,我们来任选。

      又要超时。

      分情况讨论:

      1.选的是不同联通块内的点:连出的边覆盖了Y集合内所有的点,又因为x_i>=1,所以\sum_{i=1}^{n}x_i>=n\rightarrow \begin{vmatrix} Y \end{vmatrix}>=\begin{vmatrix} X \end{vmatrix},所以右边的点肯定不少于左边选出来的点。

      2.选的是相同联通块内的点,那么是不是要满足对于每一个联通块的大小都不多于其他点的xi总和,size_i<=\sum_{j\notin i} x_j

      做完了。

#include
#include
#include
#include
#include
using namespace std;

int n;
struct edge{
	int x,y,c;
	bool operator<(const edge x)const{
		return ctotw-wei[fx]) return false;
	}
	return true;
}

int main(){
	scanf("%d",&n);
	for(int i=1;i<=n-1;i++) scanf("%d %d %d",&s[i].x,&s[i].y,&s[i].c);
	for(int i=1;i<=n;i++) scanf("%d",&w[i]),totw+=w[i];
	sort(s+1,s+n);
	int ans=0;
	int l=1,r=n-1;
	while(l<=r){
		int mid=(l+r)/2;
		if(check(mid)){
			ans=mid;
			l=mid+1;
		}
		else r=mid-1;
	}
	printf("%d\n",s[ans+1].c);
}

 

你可能感兴趣的:(Tree,noi.ac模拟赛,Hall定理)