Bzoj3060 [Poi2012]Tour de Byteotia

3060: [Poi2012]Tour de Byteotia

Time Limit: 30 Sec  Memory Limit: 256 MB
Submit: 251  Solved: 161

Description

给定一个n个点m条边的无向图,问最少删掉多少条边能使得编号小于等于k的点都不在环上。

Input

       第一行三个整数nmk
       接下来m行每行两个整数aibi,表示aibi之间有一条无向边。

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
",ans);
45     return 0;
46 }
原文地址:https://www.cnblogs.com/SilverNebula/p/5997965.html