HDOJ2419-逆向处理操作,并查集,set

/*好题!
本题的靓处:
1.逆向处理所给操作,将集合的拆分化为整合
2.STL set的lower_bound()函数
想法非原创,来自:http://blog.csdn.net/woshi250hua/article/details/7782875
*/
#include <cstdio>
#include <set>
#include <cctype>
#include <cstring>
#include <iostream>
using namespace std;

const int NN=20002;
const int QQ=300002;

int n,m,q,w[NN];
multiset<int> Set[NN];
multiset<int> adj[NN];

int p[NN];
int find(int x)
{
    if (p[x]!=x) p[x]=find(p[x]);
    return p[x];
}

void Union(int x,int y)
{
    multiset<int>::iterator it;
    x=find(x);
    y=find(y);
    if (x==y) return;

    if (Set[x].size()>Set[y].size()) swap(x,y); //这句优化有从TLE到AC的奇效
    p[x]=y;
    for (it=Set[x].begin(); it!=Set[x].end(); it++) Set[y].insert(*it);
    Set[x].clear(); //及时释放空间
}

int x[QQ],y[QQ];
char ope[QQ];
int main()
{
    int T,cas=0;
    int a,b,z,fa,fb,fx,fy;
    multiset<int>::iterator it;
    while (~scanf("%d%d%d",&n,&m,&q))
    {
        for (int i=1; i<=n; i++)
        {
            scanf("%d",&w[i]);
            Set[i].clear();
            p[i]=i;
        }
        for (int i=1; i<=m; i++)
        {
            scanf("%d%d",&a,&b);
            if (a<b) adj[a].insert(b);//之前一直用map,出现了内存错误,只好借鉴他人的set写法
            else     adj[b].insert(a);
        }

        for (int i=1; i<=q; i++)
        {
            ope[i]=getchar();
            while (!isalpha(ope[i])) ope[i]=getchar();
            scanf("%d %d",&a,&b);
            x[i]=a; y[i]=b;
            if (ope[i]=='E')
            {
                if (a<b) adj[a].erase(adj[a].find(b));
                else     adj[b].erase(adj[b].find(a));
            }
            else if (ope[i]=='U') y[i]=w[a],w[a]=b;
        }

        //the final graph
        for (int i=1; i<=n; i++) Set[i].insert(w[i]);
        for (int i=1; i<=n; i++)
        {
            for (it=adj[i].begin(); it!=adj[i].end(); it++) Union(i,*it);
            adj[i].clear(); //及时释放空间
        }

        //deal with the operations
        int cnt=0;
        double sum=0;
        for (int i=q; i; i--)
        {
            a=x[i]; b=y[i];
            if (ope[i]=='F')
            {
                fa=find(a);
                it=Set[fa].lower_bound(b);
                if (it!=Set[fa].end()) sum+=*it;
                cnt++;
            }
            else if (ope[i]=='U')
            {
                fa=find(a);
                Set[fa].erase(Set[fa].find(w[a]));
                Set[fa].insert(b);
                w[a]=b;
            }
            else Union(a,b);
        }
        printf("Case %d: %.3lf\n",++cas,sum/cnt);
    }
    return 0;
}

你可能感兴趣的:(优化,qq,iterator,Graph)