某近似模板題1
阿新 • • 發佈:2017-11-19
find %d mes isdigit stream 分發 得到 cnblogs pre
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