• BZOJ 1116 POI2008 CLO


    1116: [POI2008]CLO

    Time Limit: 10 Sec  Memory Limit: 162 MB
    Submit: 1152  Solved: 635
    [Submit][Status][Discuss]

    Description

    Byteotia城市有n个 towns m条双向roads. 每条 road 连接 两个不同的 towns ,没有重复的road. 你要把其中一些road变成单向边使得:每个town都有且只有一个入度

    Input

    第一行输入n m.1 <= n<= 100000,1 <= m <= 200000 下面M行用于描述M条边.

    Output

    TAK或者NIE 常做POI的同学,应该知道这两个单词的了...

    Sample Input

    4 5
    1 2
    2 3
    1 3
    3 4
    1 4

    Sample Output

    TAK

    上图给出了一种连接方式.

    HINT

     

    Source

    并查集水过,方法和游戏那道题一样

    原理是(抄自黄学长的博客)

    这题令我突然想到了scoi游戏
    首先我们可以推出一个性质,当且仅当某一个连通块中没有环存在输出NIE
    于是我们可以用并查集把这题水过。。
    给每个连通块的根一个标记
    合并俩个连通块时只要任意一个连通块带有标记新的连通块就带有标记
    如果一条边的俩个点已经在同一个连通块内了,直接将根打上标记即可
    然后最后扫一遍,如果哪个连通块没有标记的话输出NIE
    否则最后输出TAK
    #include <bits/stdc++.h>
    #define ll long long
    using namespace std;
    inline int read(){
        int x=0;int f=1;char ch=getchar();
        while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
        while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    const int MAXN=1e6+10;
    int f[MAXN],vis[MAXN]={};
    inline int getfather(int x){
        return x==f[x]?x:f[x]=getfather(f[x]);
    }
    int main(){
        //freopen("All.in","r",stdin);
        //freopen("a.out","w",stdout);
        int n=read();int m=read();
        for(int i=1;i<=n;i++){
            f[i]=i;
        }
        for(int i=1;i<=m;i++){
            int xx=read();int yy=read();
            int fx=getfather(xx);int fy=getfather(yy);
            if(fx==fy) vis[fy]=1;
            else vis[fy]|=vis[fx],vis[fx]|=vis[fy],f[fx]=fy;
        } 
        for(int i=1;i<=n;i++){
            if(!vis[getfather(i)]){
                cout<<"NIE"<<endl;
                return 0;
            }
        }
        cout<<"TAK"<<endl;
        return 0;
    }
    

    对拍代码

    #include <bits/stdc++.h>
    #define ll long long
    using namespace std;
    int main(){
        freopen("All.in","w",stdout);
        srand(time(int(NULL)));
        int n=rand()%10007+1;
        int m=rand()%100007+1+n;
        cout<<n<<' '<<m<<endl;
        for(int i=1;i<=m;i++){
            printf("%d %d
    ",rand()%n+1,rand()%n+1);
        }
        return 0;
    }
    
  • 相关阅读:
    C语言II博客作业01
    vscode使用相关配置
    Ubuntu配置教程
    编译原理复习
    误差与过拟合
    机器学习分类
    SQL语句使用详解
    CRC模2除法
    数据链路层之差错控制(检错编码和纠错编码)->(奇偶校验码、CRC循环冗余码、海明码)
    封装成帧、帧定界、帧同步、透明传输(字符计数法、字符串的首尾填充法、零比特填充的首尾标志法、违规编码法)
  • 原文地址:https://www.cnblogs.com/something-for-nothing/p/7976500.html
Copyright © 2020-2023  润新知