首页 > 技术文章 > HDU 5486 Difference of Clustering 暴力模拟

LMCC1108 2019-09-10 00:29 原文

Difference of Clustering HDU - 5486 

题意:有n个实体,新旧两种聚类算法,每种算法有很多聚类,在同一算法里,一个实体只属于一个聚类,然后有以下三种模式。

第一种分散,新算法的某几个聚类是旧算法某个聚类的真子集。

第二种聚合,旧算法的某几个聚类是新算法某个聚类的真子集。

第三种1:1,新算法的某个聚类跟旧算法某个聚类相同。

问每种模式存在多少个?

实路上很明了,就是模拟,而且每个实体最多遍历到一次,所以时间上不用担心。

先把聚类的编号hash,把每个实体分配到相应的聚类里,然后遍历新算法的所有聚类,再遍历每个聚类里的每个实体,用set保存这个实体相应的旧算法的聚类。

然后就是分情况讨论,如果set里的元素大于1,很明显就是分散,我们遍历set里的旧算法的聚类,然后遍历实体,看实体的编号是不是都对应当前遍历的新算法的编号

如果set里元素刚好是1,就看这个唯一对应的旧算法的聚类大小,如果等于当前遍历的新算法的大小,就是1:1了,否则我们考虑聚合的情况,处理跟分散差不多

遍历这个旧算法的聚类里的实体,用set保存这个实体相应的新算法的聚类,遍历set里的新算法的聚类,然后遍历实体,看实体的编号是不是都对应这个旧算法的编号

这里要注意的就是标记一下遍历的新算法的聚类的编号,然后后面遍历到这个聚类直接跳过就行。

具体实现上,stl用的好的话很好实现的,需要注意的就是内存的问题。clear是不会清空内存的,所有会超内存,所以用swap,

还有二维vector,vector<int> pp1[N],pp2[N]这样开的话也会超内存,改成vector< vector<int> > 动态分配内存就OK了。

主要是想保存一些这个swap和二维vector降低内存的方法,还有无序map。解法的话网上有个思路,把给出的关系转换成图,然后dfs判断点的度数就行了。

 1 #include<cstdio>
 2 #include<tr1/unordered_map>
 3 #include<vector>
 4 #include<set>
 5 using namespace std;
 6 typedef long long ll;
 7 const int N=1e6+2;
 8 const ll M=1e10+11;
 9 tr1::unordered_map<ll,int> mmp;
10 vector< vector<int> > pp1,pp2;//记录相应的聚类里的实体 
11 set<int> temp;
12 bool vis[N];
13 int match1[N],match2[N];//记录实体对应的聚类 
14 int main(){
15     int t=1,T,n,cnt1,cnt2,id1,id2;
16     ll c1,c2;
17     scanf("%d",&T);
18     while(t<=T){
19         cnt1=cnt2=0;
20         tr1::unordered_map<ll,int>().swap(mmp);
21         vector< vector<int> >().swap(pp1);
22         vector< vector<int> >().swap(pp2);
23         pp1.push_back(vector<int>());
24         pp2.push_back(vector<int>());
25         scanf("%d",&n);
26         for(int i=0;i<=n;i++) vis[i]=false;
27         for(int i=1;i<=n;i++){
28             scanf("%lld%lld",&c1,&c2);
29             c2+=M;
30             if(!mmp[c1]) mmp[c1]=++cnt1;
31             if(!mmp[c2]) mmp[c2]=++cnt2;
32             id1=mmp[c1];id2=mmp[c2];
33             if(cnt1>=(int)pp1.size())
34                 pp1.push_back(vector<int>());
35             if(cnt2>=(int)pp2.size())
36                 pp2.push_back(vector<int>());
37             pp1[id1].push_back(i);
38             pp2[id2].push_back(i);
39             match1[i]=id1;
40             match2[i]=id2;
41         }
42         int ans1=0,ans2=0,ans3=0;
43         for(int i=1;i<=cnt1;i++){
44             if(vis[i]) continue;
45             set<int>().swap(temp);
46             for(int j=0;j<(int)pp1[i].size();j++)
47                 temp.insert(match2[pp1[i][j]]);
48             if((int)temp.size()>1){
49                 bool flag=true;
50                 for(set<int>::iterator it=temp.begin();it!=temp.end()&&flag;it++){
51                     id2=*it;
52                     for(int k=0;k<(int)pp2[id2].size()&&flag;k++){
53                         id1=pp2[id2][k];
54                         if(match1[id1]!=i) flag=false;
55                     }
56                 }
57                 if(flag) ans1++;
58             }else{
59                 id2=*temp.begin();
60                 if((int)pp2[id2].size()!=(int)pp1[i].size()){
61                     set<int>().swap(temp);
62                     for(int j=0;j<(int)pp2[id2].size();j++){
63                         id1=pp2[id2][j];
64                         if(match1[id1]!=i) temp.insert(match1[id1]);
65                     }
66                     bool flag=true;
67                     for(set<int>::iterator it=temp.begin();it!=temp.end();it++){
68                         id1=*it;
69                         vis[id1]=true;
70                         for(int k=0;k<(int)pp1[id1].size();k++){
71                             int id3=pp1[id1][k];
72                             if(match2[id3]!=id2){
73                                 flag=false;
74                                 break;
75                             }
76                         }
77                     }
78                     if(flag) ans2++;
79                 }else ans3++;
80             }
81         }
82         printf("Case #%d: %d %d %d\n",t++,ans1,ans2,ans3);
83     }
84     return 0;
85 }
stl好啊

推荐阅读