


这一题的大意是说,给出M个通话记录,让我们找嫌疑人,一个人如果超过K次短通话记录给不同的人每天,但是不超过20%的人打回来,那么它就是一个嫌疑人,而且如果两个怀疑的人互相打电话我们认为他们可能属于团伙
短通话是指总时长不超过5分钟.最后需要把属于一个团伙按照编号从小到大的顺序输出。不同的团伙也按照从编号从小到大的顺序输出。
题目中的数据范围比较小,模拟这个过程并不难:
cpp
#include<bits/stdc++.h>
#include<iostream>
using namespace std;
//从大量的通话记录中探测怀疑的人
//一个人必须被探测作为一个怀疑者如果他做出了
//超过K次短通话记录给不同的人每天
//但是不超过20%的人打回来
//而且如果两个怀疑的人互相打电话我们认为他们可能属于团伙
//短通话是指总时长不超过K分钟
int K;
int N;
int M;
int f[1005];
int n[1005][1005];
int cnt[1005];
int callback[1005];
int find(int x)
{
if(f[x]!=x)
{
return find(f[x]);
}
else
{
return x;
}
}
bool flag[1005];
int main()
{
cin>>K>>N>>M;
for(int i=0;i<1005;i++)
{
f[i]=i;
}
for(int i=0;i<M;i++)
{
int caller;
int receiver;
int duration;
cin>>caller>>receiver>>duration;
n[caller][receiver]+=duration;
}
for(int i=1;i<=N;i++)
{
for(int j=1;j<=N;j++)
{
if(i!=j)
{
if(n[i][j]<=5&&n[i][j]>0)
{
//不能超过阈值才算做符合条件的通话
cnt[i]++;
}
if(n[i][j]>0&&n[i][j]<=K&&n[j][i]>0)
{
callback[i]++;
}
}
}
}
//cout<<cnt[1]<<endl;
vector<int> crime;
for(int i=1;i<=N;i++)
{
if(cnt[i]>K)
{
int x=cnt[i];
//cout<<x<<" ";
if(callback[i]<=x*0.2)
{
crime.push_back(i);
}
}
}
if(crime.size()==0)
{
cout<<"None"<<endl;
return 0;
}
for(int i=0;i<crime.size();i++)
{
for(int j=i+1;j<crime.size();j++)
{
if(n[crime[i]][crime[j]]>0&&n[crime[j]][crime[i]]>0)
{
int fa=find(crime[i]);
int fb=find(crime[j]);
if(fa==fb)
{
//说明在一个帮里面不用管
}
else
{
f[fa]=fb;
}
}
}
}
vector<vector<int>> total(N);
int t=0;
//我们现在把同一个帮派的放到了一个并查集里面了
for(int i=0;i<crime.size();i++)
{
if(flag[crime[i]])
{
continue;
}
cout<<crime[i];
for(int j=i+1;j<crime.size();j++)
{
if(find(crime[i])==find(crime[j]))
{
cout<<" "<<crime[j];
flag[crime[j]]=1;
}
}
cout<<endl;
}
return 0;
}
注意嫌疑人是否是在同一个团伙中,用并查集来判断。
最后的按顺序输出对我来说不太轻松,我参考了柳神的输出方法
实际上可以用哈希表分组输出:
cpp
map<int, vector<int>> groups;
for (int x : crime)
{
int root = find(x);
groups[root].push_back(x);
}
//组内排序
for (auto &g : groups)
{
sort(g.second.begin(), g.second.end());
}
//组间排序
vector<vector<int>> ans;
for (auto &g : groups)
{
ans.push_back(g.second);
}
sort(ans.begin(), ans.end(), [](const vector<int>& a, const vector<int>& b){
return a[0] < b[0];
});
这种方法挺麻烦的,但好理解。
二维数组不同组间的排序还可以这样输出:
cpp
vector<pair<int, vector<int>>> ans;
bool cmp(const vector<int>& a, const vector<int>& b)
{
return a[0] < b[0];
}
sort(ans.begin(), ans.end(), cmp);
总结:并查集+模拟