题解 AT5201 【[AGC038D] Unique Path】

· · 题解

首先如果 a,b 只有一条路径,且 b,c 只有一条路径,那么 a,c 一定只有一条路径。显而易见的,a,c 之间的合法路径只能为 a\rightarrow b\rightarrow c 。因此将所有的由 0 类边连起来的点放在一起,形成一个联通块(显然只能是一棵树)。

假设有 k 个联通块,因为每个联通块都是一棵树,因此还剩下 m-n+k 条边。

如果这个时候没有 1 类边的话:

如果有 1 类边:

维护一下联通块,然后判断 m 是否在合法区间内即可(注意判断 m<n-1)。

const int N=1e5+5;
int n,k,q,a[N],b[N],c[N],fa[N];
ll m;

int find(int x) {return x==fa[x]?x:fa[x]=find(fa[x]);}

int main() {
    IN(n,m,q),k=n;
    lep(i,1,q) IN(a[i],b[i],c[i]);
    lep(i,1,n) fa[i]=i;

    bool flag=false;
    lep(i,1,q) if(!c[i]) {if(find(a[i])!=find(b[i])) fa[find(a[i])]=find(b[i]),--k;}
    lep(i,1,q) if(c[i]) {
        flag=true;
        if(find(a[i])==find(b[i])) return puts("No"),0;
    }

    if(m<n-1) return puts("NO"),0;
    if(!flag) puts((k-1<=m-n+k&&m-n+k<=1ll*k*(k-1)/2)?"Yes":"No");
    else puts((k>2&&k<=m-n+k&&m-n+k<=1ll*k*(k-1)/2)?"Yes":"No");
    return 0;
}