[BZOJ3060] [Poi2012]塔Byteotia

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

题目分析

我们先把两个端点的编号都大于K的边扔到并查集里
然后枚举剩下的边,如果加入这条边不会出现环 就加入到并查集里 否则就删去这条边

#include <cstdio>
#include <algorithm>
using namespace std;
int f[1100000];
int q[3100000][3];
int find(int x)  
{  
    return f[x]==x?x:f[x]=find(f[x]); 
}  
int main()
{
    int n,m,k;
    scanf("%d%d%d",&n,&m,&k);
    for(int i=1;i<=n;i++) f[i]=i;
    int tmp=0;
    for(int i=1;i<=m;i++)
    {
        int a,b;
        scanf("%d%d",&a,&b);
        if(a<=k||b<=k)
            tmp++,q[tmp][1]=a,q[tmp][2]=b;
        else
        {
            int x=find(a),y=find(b);
            if(x!=y) f[x]=y;
        }
    }
    int ans=0;
    for(int i=1;i<=tmp;i++)
    {
        int x,y;
        x=find(q[i][1]);
        y=find(q[i][2]);
        if(x==y) ans++;
        else f[x]=y;
    }
    printf("%d",ans);    
}

发表评论

邮箱地址不会被公开。 必填项已用*标注