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

某近似模板题1

时间:2017-11-19 11:07:24      阅读:90      评论:0      收藏:0      [点我收藏+]

标签:down   class   read   描述   --   inpu   getchar   define   ++i   

P2097 资料分发1
题目描述

有一些电脑,一部分电脑有双向数据线连接。如果一个电脑得到数据,它可以传送到的电脑都可以得到数据。现在,你有这个数据,问你至少将其输入几台电脑,才能使所有电脑得到数据。

输入输出格式

输入格式:
第一行两个数n,m。n是点数,m是边数。

接下来m行,每行2个整数p,q表示p到q有一条双向数据线。

输出格式:
一个整数,表示至少输入的电脑数量。

输入输出样例

输入样例#1: 复制
4 5
1 2
1 3
2 3
2 1
3 4
输出样例#1: 复制
1
说明

对于30%的数据:n<=100,m<=1000

对于60%的数据:n<=2000,m<=100000

对于100%的数据:n<=100000, m<=200000

数据不保证没有重边,不保证没有自回环

用时168-92-68-56ms

看到有人用Tarjan求强联通分量做
23333
dfs,复杂度O(n)
并查集,复杂度O(input左右)
路径压缩,读入优化

#include<iostream>
#include<cstdio>
#define N 100005
using namespace std;

int a,b;
int n,m;
int fa[N];
int siz[N];

void init(){
    for(int i=1;i<=n;++i)
        fa[i]=i;
    for(int i=1;i<=n;++i)
        siz[i]=1;
}

int find(int s){
    if(fa[s]!=s)fa[s]=find(fa[s]);
    return fa[s];
}

void read(int &s){
    char ch=getchar();
    for(;!isdigit(ch);ch=getchar());
    for(s=0;isdigit(ch);s=s*10+ch-'0',ch=getchar());
}

int faa,fab;

bool un(int a,int b){
    faa=find(a);
    fab=find(b);
    if(faa>fab){
        faa^=fab;
        fab^=faa;
        faa^=fab;
    }
    if(faa!=fab)return fa[faa]=fab,siz[fab]+=siz[faa];
    return false;
}

int ans;

int main(){
    while(~scanf("%d%d",&n,&m)){
        init();ans=n; 
        for(int i=1;i<=m;++i){
            read(a),read(b);
            if(un(a,b))ans--;
        }
        printf("%d\n",ans);
    }
    return 0;
}

某近似模板题1

标签:down   class   read   描述   --   inpu   getchar   define   ++i   

原文地址:http://www.cnblogs.com/qdscwyy/p/7859049.html

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