Bzoj3060 [Poi2012]Tour de Byteotia
3060: [Poi2012]Tour de Byteotia
Time Limit: 30 Sec Memory Limit: 256 MBSubmit: 251 Solved: 161
Description
给定一个n个点m条边的无向图,问最少删掉多少条边能使得编号小于等于k的点都不在环上。
Input
第一行三个整数n,m,k;
接下来m行每行两个整数ai,bi,表示ai和bi之间有一条无向边。
Output
一个整数,表示最少的删边数量。
Sample Input
11 13 5
1 2
1 3
1 5
3 5
2 8
4 11
7 11
6 10
6 9
2 3
8 9
5 9
9 10
Sample Output
3
HINT
数据范围:
对于100%的数据满足:1 ≤ n ≤ 1,000,000,1 ≤ m ≤ 2,000,000,1 ≤ k ≤ n。
Source
首先把两端点序号都大于k的边加入生成图中,接着枚举其他边,如果加入后不会形成新环,就加入(新加入的部分是生成树,所以可以像kruskal那样加边)
1 /*by SilverN*/ 2 #include<algorithm> 3 #include<iostream> 4 #include<cstring> 5 #include<cstdio> 6 #include<cmath> 7 #include<vector> 8 using namespace std; 9 const int mxn=2000010; 10 int read(){ 11 int x=0,f=1;char ch=getchar(); 12 while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();} 13 while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();} 14 return x*f; 15 } 16 int n,m,k; 17 int fa[mxn]; 18 int find(int x){ 19 if(fa[x]==x)return x; 20 return fa[x]=find(fa[x]); 21 } 22 int x[mxn],y[mxn]; 23 int main(){ 24 n=read();m=read();k=read(); 25 int i,j; 26 for(i=1;i<=n;++i)fa[i]=i; 27 int u,v; 28 for(i=1;i<=m;++i){ 29 x[i]=read();y[i]=read(); 30 if(x[i]>y[i])swap(x[i],y[i]); 31 if(x[i]>k && y[i]>k){ 32 u=find(x[i]);v=find(y[i]); 33 if(u!=v)fa[v]=u; 34 } 35 } 36 int ans=0; 37 for(i=1;i<=m;++i){ 38 if(x[i]<=k || y[i]<=k){ 39 u=find(x[i]);v=find(y[i]); 40 if(u!=v) fa[v]=u; 41 else ans++; 42 } 43 } 44 printf("%d\n",ans); 45 return 0; 46 }
本文为博主原创文章,转载请注明出处。