本题与一般的图遍历问题相区别的地方在于:对每个边仅访问一次。解决的办法是当访问到图中的某一个顶点u时,试图去访问该顶点u所有邻边,并且在访问过后就删除掉这条已经访问过的邻边,当然如果与该顶点u相连的另外一个顶点v未被访问过的话就深度优先访问v这个顶点直到所有的顶点都被访问完毕。
另附上本题代码:
#include<cstdio>
#include<map>
#include<string>
#include<vector>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn = 2010;
map<string,int> Stoi;
map<int,string> Itos;
int cnt=0;//record the number of people
int change(string name)//change string to int
{
if(Stoi.count(name)==0){
Stoi[name]=cnt;
Itos[cnt]=name;
cnt++;
}
return Stoi[name];
}
int G[maxn][maxn]={0}, W[maxn]={0};//weight of edge and weight of point
bool vis[maxn] = {false};
int totalWeight=0;
int maxTime=-1;
int head;
int peopleInGang=0;
void DFS(int u)
{
vis[u]=true;
peopleInGang++;
if(W[u]>maxTime){
maxTime = W[u];
head = u;
}
for(int v=0; v<cnt; v++){
if(G[u][v]!=0){
totalWeight+=G[u][v];
G[u][v]=G[v][u]=0;
if(vis[v]==false){
DFS(v);
}
}
}
}
struct Head{
string name;
int peopleInGang;
};
bool cmp(Head a,Head b)
{
return a.name<b.name;
}
int main()
{
int N,K,time,u,v;
string name1,name2;
scanf("%d%d",&N,&K);
for(int i=0; i<N; i++){
cin>>name1>>name2>>time;
u = change(name1);
v = change(name2);
G[u][v] += time;
G[v][u] += time;
W[u] += time;
W[v] += time;
}
struct Head tmp;
vector<struct Head> ans;
for(int u=0; u<cnt; u++){
if(vis[u]==false){
totalWeight=0;
maxTime=-1;
peopleInGang=0;
DFS(u);
tmp.name = Itos[head];
tmp.peopleInGang = peopleInGang;
if(totalWeight>K&&peopleInGang>2){
ans.push_back(tmp);
}
}
}
printf("%d\n",ans.size());
sort(ans.begin(),ans.end(),cmp);
for(int i=0; i<ans.size(); i++){
cout<<ans[i].name<<" "<<ans[i].peopleInGang<<endl;
}
return 0;
}