这道题目刚开始想用并查集来做,但是其实不通的,因为有可能是环,不确保是一个图。
这道题目第一想法应该是用DFS来做,BFS也行,不过用DFS习惯了。
// 1034.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include<stdio.h> #include<string.h> #include<string>//string 使用c++的string,如果使用c语言的string,那么就会导致map声明时候的问题,所以加载时候最好使用string; using namespace std; #include<map> #include<vector> #include<algorithm> using namespace std; map<string,int> dir; map<int,string> dir2; struct Pair { Pair(int d,int n) { data=d; next=n; } int data; int next; }; vector<Pair> v; vector<int> tmp; bool visited[2010][2010]; bool nodev[2010]; int m[2010][2010]; int weight[2010]; int size; int max_index=-1,Max=-1,sum=0,num=0;//最大是谁,和是多少,有多少个人 int findIndex(string str) { map<string,int>::iterator it=dir.find(str); if(it!=dir.end()) return it->second; else { dir.insert(make_pair(str,dir.size()+1)); dir2.insert(make_pair(dir2.size()+1,str)); return dir.size(); } } string findString(int index) { map<int,string>::iterator it=dir2.find(index); /*for(it=dir.begin();it!=dir.end();it++) { if(it->second==index) { ret=it->first; break; } }*/ return it->second; } bool cmp(Pair a,Pair b) { if(findString(a.data)<findString(b.data)) { return true; } return false; } void dfs(int index) { nodev[index]=true; if(find(tmp.begin(),tmp.end(),index)==tmp.end()) { tmp.push_back(index); } for(int i=1;i<=size;i++) { if(i==index) continue; if(!visited[i][index]&&m[i][index]!=0) { sum=sum+m[i][index]; weight[i]+=m[i][index]; weight[index]+=m[i][index]; if(weight[i]>Max) { Max=weight[i]; max_index=i; } if(weight[index]>Max) { Max=weight[index]; max_index=index; } if(find(tmp.begin(),tmp.end(),i)==tmp.end()) { tmp.push_back(i); } visited[i][index]=visited[index][i]=true; dfs(i); } } } int main() { int n,k; int t; int index1,index2; freopen("1034-in.txt","r",stdin); char a[20]; char b[20]; while(scanf("%d%d",&n,&k)!=EOF) { memset(m,0,sizeof(int)*2010*2010); memset(visited,0,sizeof(bool)*2010*2010); memset(weight,0,sizeof(int)*2010); memset(nodev,0,sizeof(int)*2010); for(int i=1;i<=n;i++) { scanf("%s%s%d",a,b,&t); index1=findIndex(string(a));//string char c style index2=findIndex(string(b)); if(m[index1][index2]!=0) { m[index1][index2]=m[index2][index1]=m[index1][index2]+t; } else { m[index1][index2]=m[index2][index1]=t; } } //search size=dir.size(); while(true) { int unvis=-1; for(int i=1;i<=size;i++) { if(!nodev[i]) { unvis=i; break; } } if(unvis==-1) break; dfs(unvis); if(sum>k&&tmp.size()>=3) v.push_back(Pair(max_index,tmp.size())); tmp.clear(); max_index=-1,Max=-1,sum=0,num=0; } int count=v.size(); printf("%d\n",count); sort(v.begin(),v.end(),cmp); for(int i=0;i<count;i++) { printf("%s %d\n",findString(v[i].data).c_str(),v[i].next); } } return 0; }
1)在用字符串做索引的时候,我喜欢用map来查找对应的索引值,这样效率很高,logn的算法。这道题目有从string到index的索引,有从index到string的索引。刚开始建立的是从string到index的索引,这样从index到string索引时候,我是采用遍历的方式来比对string的。这样导致了最后一个case超时,但是大部分时候内存是不会超过限制的,用内存换时间是很合得来的。所以我又建立了一个以index为索引,值为string的索引。这样最后一个测试用例就过去了。
2) 这道题目dfs遍历的是边,而不是顶点,当然还是以顶点作为切入。这不是一个树或者图,这是一个有可能不连通的有环图。
3)dfs时候需要返回多个值,直接以全局变量放进去了,每次遍历完一片区域就清空。
注意:
这道题目描述的是变数不超过1000,加入1000条边都是不相连的,那么就会有2000个顶点。有一个测试用例顶点数目很多。