码迷,mamicode.com
首页 > 其他好文 > 详细

$bzoj1116-POI2008$ $CLO$ 并查集

时间:2019-05-10 14:35:06      阅读:99      评论:0      收藏:0      [点我收藏+]

标签:ring   scan   max   algorithm   输入格式   ++   ==   names   \n   

  • 题面描述
    • \(Byteotia\)城市有\(n\)\(towns\)\(m\)条双向\(roads\). 每条 \(road\) 连接 两个不同的 \(towns\) ,没有重复的\(road\).
    • 你要把其中一些\(road\)变成单向边使得:每个\(town\)都有且只有一个入度
  • 输入格式
    • 第一行输入\(n,m\). \((1 \leq n\leq 10^5,1\leq m \leq 2*10^5)\)
    • 下面\(M\)行用于描述\(M\)条边.
  • 输出格式
    • \(TAK/NIE\)
  • 题解
    • 考虑每个点都有一个入度,因此 被定向的边数\(=\)点数,因此不难想到被定向后的边组成的图形是一个基环外向树,因此在原图每个联通块中,必然要存在一个环,不然就不能达成目的
    • 因此用并查集判断是否有环即可
      • 具体来说,一条一条边加入,当将要被加入的点已经在要加入的集合中时即存在环
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN=1e5+5;
const int MAXM=1e6+6;
int n,m,fa[MAXN];
int mark[MAXN];
int find(int x){ return fa[x]==x?x:fa[x]=find(fa[x]); }
void uion(int x,int y){ 
    int fx=find(x),fy=find(y);
    fa[fx]=fy;
    mark[fy]|=mark[fx];
}
int main(){
    scanf("%d%d",&n,&m);
    for (int i=1;i<=n;i++) fa[i]=i;
    for (int i=1;i<=m;i++){
        int u,v; scanf("%d%d",&u,&v);
        int fu=find(u),fv=find(v);
        if (fu!=fv) uion(u,v);
        else mark[fu]=1;
    }
    for (int i=1;i<=n;i++){
        int fi=find(i);
        if (!mark[fi]) return printf("NIE\n"),0;
    }
    printf("TAK\n");
    return 0;
}

$bzoj1116-POI2008$ $CLO$ 并查集

标签:ring   scan   max   algorithm   输入格式   ++   ==   names   \n   

原文地址:https://www.cnblogs.com/shjrd-dlb/p/10844153.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!