Unique Path AGC 038 D

Unique Path

AGC 038 D

考虑如果两个点之间只能有一个边它们就把它们缩起来,那么最后缩起来的每一块都只能是一棵树。

如果两个点之间必须不止一个边,并且在一个连通块,显然无解。

首先把所有树给连好,现在的可用的边的数量只有 $ m - n + c $ 了。

然后两个连通块之间如果有超过一条边,连通块内部的点显然不只一条路径了。

其他情况,如果我们给连通块连边的时候每个连通块都只一直用一个点来往外连,就可以保证所有连通块都满足要求。

  • 如果不存在两个点之间不只一个边的情况

    那么只要可用的边的数量多余 $ c-1 $ 并且不超过把这一堆连通块连成完全图的情况,都是可以的。

  • 如果存在

    那么可用的边数量必须多余 $ c $ ,因为至少要连成一个环,否则不能满足这个不只一个边的条件。

其实还有些小情况,想一下就发现是对的。

记得开longlong

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<vector>
using namespace std;
#define int long long
#define MAXN 200006
#define pb push_back
#define pii pair<int,int>
#define mp make_pair
int n , m , q;

int fa[MAXN];
int find( int x ) {
	return x == fa[x] ? x : fa[x] = find( fa[x] );
}
struct dl{
	int u , v;
} d[MAXN] ;
int cnt , c;

signed main( ) {
	cin >> n >> m >> q;
	for( int i = 1 ; i <= n ; ++ i ) fa[i] = i;
	for( int i = 1 , u , v , c ; i <= q ; ++ i ) {
		scanf("%lld%lld%lld",&u,&v,&c);
		++ u , ++ v;
		if( !c ) {
			fa[find( u )] = find( v );
		} else {
			d[++ cnt] = (dl) { u , v };
		}
	}
	for( int i = 1 , u , v ; i <= cnt ; ++ i ) {
		if( find( d[i].u ) == find( d[i].v ) )
			return puts("No") , 0;
	}
	for( int i = 1 ; i <= n ; ++ i ) if( fa[i] == i )
		++ c;
	int ed = m - n + c;
	if( !cnt ) return puts( ( ed >= c - 1 && ed <= c * ( c - 1 ) / 2 ) ? "Yes" : "No" ) , 0;
	else return puts( ( ed >= c && ed <= c * ( c - 1 ) / 2 ) ? "Yes" : "No" ) , 0;
}
posted @ 2019-10-11 06:49  yijan  阅读(204)  评论(0)    收藏  举报