1024 [SCOI2010]游戏 贪心|dfs|并查集

链接:https://ac.nowcoder.com/acm/contest/23156/1024 来源:牛客网

题目描述 lxhgww最近迷上了一款游戏,在游戏里,他拥有很多的装备,每种装备都有2个属性,这些属性的值用[1,10000]之间的数表示。当他使用某种装备时,他只能使用该装备的某一个属性。并且每种装备最多只能使用一次。 游戏进行到最后,lxhgww遇到了终极boss,这个终极boss很奇怪,攻击他的装备所使用的属性值必须从1开始连续递增地攻击,才能对boss产生伤害。也就是说一开始的时候,lxhgww只能使用某个属性值为1的装备攻击boss,然后只能使用某个属性值为2的装备攻击boss,然后只能使用某个属性值为3的装备攻击boss……以此类推。现在lxhgww想知道他最多能连续攻击boss多少次? 输入描述:

输入的第一行是一个整数N,表示lxhgww拥有N种装备 接下来N行,是对这N种装备的描述,每行2个数字,表示第i种装备的2个属性值

输出描述:

输出一行,包括1个数字,表示lxhgww最多能连续攻击的次数。

示例1 输入 复制

3 1 2 3 2 4 5

输出 复制

2

备注:

对于30%30%30% 的数据,保证N≤1000N \leq 1000N≤1000 对于100%100%100% 的数据,保证N≤1000000N \leq 1000000N≤1000000

贪心:

是我搞错了还是大佬搞错了。这题直接贪心不就行了,为啥要二分图匹配,。。。

给每个节点按照比较小的关键字排序,然后比较大的关键字排序不排序都行

然后从前往后查找每个1,2,3,4,5.。。和每个节点一一比较

如果每个节点的a和b都不满足条件,把这个b保存下来,如果下次遇到了这个b值直接使用它

就a了啊。

ps:关于,一开始我还在想这题的意思是1,2,3,4,5这样连续的最长长度还是找到某个不适配的值再倒回来12345,想写个《比较》暴力的写法试一下,没想到就a了这件事,嘿嘿嘿

dfs:
将所有点连起来,然后深搜,如果搜不到重复的数,说明不是树,取这个连通块走过的最大值


并查集:
开一个数组存每个连通块的最大值
如果说一个连通块里有两个值重复出现,说明连通块里的值是连成了树的,这个连通块的所有值都能走
遍历所有连通块,找到不是数的,最大值最小的连通块的最大值,-1就是结果(因为只是一棵树,边数 = 点数 - 1 ,边不够,最后一个点取不到)

//-------------------------代码----------------------------

//#define int LL
const int N = 1e6+10;
int n,m;
struct Q {
    int a,b;
    bool operator<(const Q & t )const {
        if(a == t.a) {
            return b < t.b;
        }  else return a < t.a;
    }
};
Q q[N];
int vis[N];
void solve()
{
     cin>>n;
//     V<V<int>>mp(n+1,V<int>(m+1));
     fo(i,1,n) {
         cin>>q[i].a>>q[i].b;
         if(q[i].a > q[i].b)swap(q[i].a,q[i].b);
     }
    sort(q+1,q+1+n);
    int sum = 0;
    int l = 0;
    for(int i = 1;i<=n;i++) {
        while(vis[sum + 1]) sum ++ ,l ++ ;
        if(q[i].a == 1+sum) {
            sum ++ ; l ++ ;
        } else if(q[i].b == 1 + sum) {
            sum ++ ; l ++ ;
        } else vis[q[i].b] = true;
    }
    cout<<l<<endl;
}

signed main(){
    clapping();TLE;
    
//    int t;cin>>t;while(t -- )
    solve();
//    {solve(); }
    return 0;
}

/*样例区


*/

//------------------------------------------------------------

dfs

#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;
const int N=10100;
int n;
vector<int> edge[N];
bool vis[N];
int maxn=0;

bool dfs(int x,int fa)//fa是从哪一个点来的
{
    maxn=max(x,maxn);//找这个连通块内最大的数
    vis[x]=1;
    int flag=0;//看一下是棵树,还是比树的边数还多
    for(int i=0;i<edge[x].size();i++)
    {
        int j=edge[x][i];
        if(j==fa) continue;//如果它们是一个环,那就跳过
        if(vis[j]) {flag=1;continue;}//如果之前走过,那么说明这个连通块内的边比树的边数多。
        if(dfs(j,x)) flag=1;
    }
    return flag;
}

int main(){
    cin>>n;
    int m=0;
    while(n--)
    {
        int a,b;
        cin>>a>>b;
        edge[a].push_back(b);
        edge[b].push_back(a);
        m=max(m,a);
        m=max(m,b);
    }
    int ans=m+1;//ans是假设比最大还大1的攻击次数
    memset(vis,0,sizeof vis);
    for(int i=1;i<=m;i++)//去搜索每个点所在的连通块
    {
        maxn=0;//每次都要清零
        if(!vis[i] && !dfs(i,0))//如果这个点所在的连通块是一棵树,就去更新答案,如果比树还多一条边,那么这个连通块内的点都能到,就不用任何操作了。
            ans=min(ans,maxn);
        //cout<<ans<<endl;
    }
    cout<<ans-1<<endl;
    
    return 0;
}

----------------------------------------------------------
并查集
并查集

#include<iostream>
#include<algorithm>
using namespace std;
const int N=10010;
int fa[N],maxn[N];//maxn是比各个根结点最大的攻击次数还多1的攻击次数
bool b[N];//b是看各个根结点是不是有比n-1条边还多的边
int n;

int find(int x)
{
    return fa[x] == x ? x : fa[x] = find(fa[x]);
}

int main(){
    for(int i=1;i<N;i++)
      fa[i]=i,maxn[i]=i;
    
    cin>>n;
    for(int i=0;i<n;i++)
    {
        int x,y;
        cin>>x>>y;
        int fx=find(x);
        int fy=find(y);
        if(fx != fy)//如果根结点不一样
        {
            fa[fx]=fy;
            maxn[fy]=max(maxn[fx],maxn[fy]);//因为根结点变成fy,所以只用更新fy
            b[fy]=(b[fx] || b[fy]);//两个集合中只要有一个是有多至少一条边的,那么这两个集合合并后,集合里的每个数都能用上
        }
        else//根结点一样
        {
            b[fx]=1;//多连了一条边
        }
    }
    int ans=10001;
    for(int i=1;i<=10000;i++)
    {
        if(fa[i] == i)
        {
            if(b[i]==0)//如果集合内不能用上所有数
                ans=min(ans,maxn[i]);
        }
    }
    
    cout<<ans-1<<endl;
    
    return 0;
}

posted @ 2022-07-02 23:45  er007  阅读(67)  评论(0编辑  收藏  举报