这道题目一开始的看了《算法笔记》上面的代码,很诧异为啥用dfs去遍历一个cluster,并且还做了删除上一条边的操作。自己写了代码以后就想清楚了。因为这不是一个简单的遍历操作,你不能把访问过的节点标记了就不访问了。图里面会有环,可能两个访问过的节点中间也会有边,所以需要下面不同于寻常的bfs,加入了下面这段代码:
for(int i=1;i<=numperson;i++)
{
if(aj[tmp][i]>0&&visit[i]==0)
{
wei_tot+=aj[tmp][i];
q.push(i);
visit[i]=1;
vis[tmp][i]=1;
vis[i][tmp]=1;
continue;
//rela_num++;
}
if(aj[tmp][i]>0&&visit[i]==1&&vis[tmp][i]==0)
{
wei_tot+=aj[tmp][i];
vis[tmp][i]=1;
vis[i][tmp]=1;
continue;
}
大概的意思就是如果节点没有访问过,就把它加入队列;如果访问过了,就看一下有没有没有访问过的边。其实这道题目用bfs更直接,所以自己写了一遍,事实证明是可行的。很多东西还是要自己动手才有用啊。
#include <cstdio>
#include <algorithm>
#include <iostream>
#include <vector>
#include <string.h>
#include <queue>
#include <map>
using namespace std;
const int maxn = 2002;
int n,thres;
map<string,int> ans;
map<int,string> aa;
map<string,int> bb;
int gnum = 0;
int aj[maxn][maxn]={0};
int visit[maxn]={0};
int vis[maxn][maxn]={0};
int weight[maxn]={0};
int numperson=0;
void bfs(int cur)
{
//gnum++;
int rela_num=0;
visit[cur]=1;
int wei_max = 0;
int flag;
int wei_tot = 0;
queue<int> q;
q.push(cur);
while(!q.empty())
{
int tmp=q.front();
q.pop();
rela_num++;
if(weight[tmp]>wei_max)
{
wei_max=weight[tmp];
flag=tmp;
}
for(int i=1;i<=numperson;i++)
{
if(aj[tmp][i]>0&&visit[i]==0)
{
wei_tot+=aj[tmp][i];
q.push(i);
visit[i]=1;
vis[tmp][i]=1;
vis[i][tmp]=1;
continue;
//rela_num++;
}
if(aj[tmp][i]>0&&visit[i]==1&&vis[tmp][i]==0)
{
wei_tot+=aj[tmp][i];
vis[tmp][i]=1;
vis[i][tmp]=1;
continue;
}
}
}
if(rela_num>2&&wei_tot>thres)
{
gnum++;
ans[aa[flag]]=rela_num;
}
//cout<<wei_tot<<endl;
}
int main()
{
int i,m,tmp;
scanf("%d%d",&n,&thres);
string st,en;
for(i=0;i<n;i++)
{
cin >> st >> en >> m;
if(bb.find(st)!=bb.end())
{
tmp = bb[st];
weight[tmp] += m;
}
else
{
bb[st]=(++numperson);
aa[numperson] = st;
weight[numperson] += m;
}
if(bb.find(en)!=bb.end())
{
tmp = bb[en];
weight[tmp] += m;
}
else
{
bb[en]=(++numperson);
aa[numperson] = en;
weight[numperson] += m;
}
aj[bb[st]][bb[en]]+=m;
aj[bb[en]][bb[st]]+=m;
}
//cout<<numperson<<endl;
for(i=1;i<=numperson;i++)
{
if(visit[i]==0)
{
bfs(i);
}
}
cout<<gnum<<endl;
map<string,int>::iterator it;
for(it=ans.begin();it!=ans.end();it++)
cout<<it->first<<" "<<it->second<<endl;
return 0;
}