51nod 1191-贪心+并查集

首先不得不承认这题写残疾了,本来是优先队列随便搞一下就过了(确保弹出来的箭能杀死兔子),这里贴一下当时另一种贪心思想写的,运用了并查集,对于箭贪心,每次杀能杀死的最大的兔子之后得到解,这里要用并查集动态维护一下x的箭杀什么兔子,乱搞一气也算过了。

 

 

#include <iostream>
#include <queue>
#include <algorithm>
#include <map>
using namespace std;
int n,m,nn;

int rib[50005];
struct A{
    int a,qb;
}arr[50005];
int index[100005];
int f[50005];
int vis[50005];
int cc[50005];
bool operator < (A a1,A a2){
    return a1.qb<a2.qb;
}
int fin(int x){
    int r=x;
    while(f[r]!=r)
        r=f[r];
    return r;
}
void mer(int a,int b){
    int fx,fy;
    fx=fin(a);
    fy=fin(b);
    if(fx!=fy)
        f[fx]=fy;
}

void solve(){
    long long ans=0;
    int cnt=0;
    for(int i=0;i<m;i++){
        int x=fin(index[arr[i].a]);
        if(x!=0){
            vis[x]--;
            if(vis[x]==0)
                mer(x,x-1);
            ans+=(long long)arr[i].qb;
            cnt++;
        }
        if(cnt==n)
            break;
    }
    if(cnt==n){
        cout<<ans<<endl;
    }
    else{
        cout<<"No Solution"<<endl;
    }
}

int main()
{
    cin>>n>>m;
    for(int i=0;i<n;i++){
        cin>>rib[i];
    }
    for(int i=0;i<m;i++){
        cin>>arr[i].a>>arr[i].qb;
    }
    sort(arr,arr+m);
    sort(rib,rib+n);

    for(int i=0;i<50005;i++){
        f[i]=i;
    }
    int num=0;
    int N=0;
    for(int i=0;i<100005;i++){
        if(num<n){
            if(i<rib[num]){
                index[i]=N;
            }
            else{
                N++;
                index[i]=N;
                vis[N]++;
                num++;
                while(rib[num]==rib[num-1]){
                    vis[N]++;
                    num++;
                }
            }
        }
        else{
                index[i]=N;
        }
    }
    solve();
    return 0;
}



posted @ 2016-03-15 20:59  zhangxianlong  阅读(92)  评论(0编辑  收藏  举报