zoukankan      html  css  js  c++  java
  • 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;
    }
    
  • 相关阅读:
    哈哈,原来这叫做“松鼠症”……并谈谈我建议的学习方法
    入坑IT十年(二)技术以外
    入坑IT都快十年了
    也来谈谈IT培训
    技术,是不是越新越好?
    十年之后再看“面向对象”
    话说,你这样根本就不应该去“创业型”公司
    我为什么不做外包
    NetTopologySuite Geometry&WKT&WKB&GeoJSON互转
    wpf 打印图片
  • 原文地址:https://www.cnblogs.com/yijan/p/agc038d.html
Copyright © 2011-2022 走看看