[关闭]
@darkproject 2017-03-31T13:37:14.000000Z 字数 2413 阅读 908

拓扑排序&欧拉路专题

集训队


A - 确定比赛名次 HDU - 1285

简单的拓扑排序,需要注意的是这里对于多种排序结果,输出字典序小的那种,这里用优先队列解决此问题,优先队列+拓扑

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <vector>
  4. #include <queue>
  5. #include <cstring>
  6. #include <algorithm>
  7. const int maxn=505;
  8. using namespace std;
  9. vector<int>G[maxn];
  10. vector<int>ans;
  11. //queue<int>q;
  12. priority_queue<int,vector<int>,greater<int>>q;
  13. int n,deg[maxn],m;
  14. void bfstop()
  15. {
  16. for(int i=1;i<=n;i++)
  17. {
  18. if(deg[i]==0)
  19. q.push(i);
  20. }
  21. while(!q.empty())
  22. {
  23. int p=q.top();
  24. q.pop();
  25. ans.push_back(p);
  26. for(int j=0;j<G[p].size();j++)
  27. {
  28. --deg[G[p][j]];
  29. if(deg[G[p][j]]==0)
  30. q.push(G[p][j]);
  31. }
  32. }
  33. }
  34. int main()
  35. {
  36. int a,b;
  37. while(scanf("%d%d",&n,&m)!=EOF)
  38. {
  39. ans.clear();
  40. for(int i=0;i<maxn;i++)
  41. G[i].clear();
  42. memset(deg,0,sizeof(deg));
  43. for(int i=1;i<=m;i++)
  44. {
  45. cin>>a>>b;
  46. G[a].push_back(b);
  47. ++deg[b];
  48. }
  49. bfstop();
  50. for(int i=0;i<ans.size()-1;i++)
  51. printf("%d ",ans[i]);
  52. printf("%d\n",ans[ans.size()-1]);
  53. }
  54. return 0;
  55. }

B - Reward HDU - 2647

老板分配工资,每个人最少888,题中给予每个人工资高低顺序,求老板最少需要分配多少工资,若没有合理方案则输出-1.
我们可以反向建图,每个点值初始化为888,然后拓扑一下,根据贪心原则应该高工资的人和低工资的差距为1老板可以取到最小分配。这里通过判断是否有环来判断是否合理,可以直接判断拓扑排序点的个数与n比较

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <queue>
  4. #include <vector>
  5. #include <cstring>
  6. const int maxn = 2e4+5;
  7. using namespace std;
  8. vector<int>G[maxn];
  9. queue<int>hyx;
  10. int cost[maxn],deg[maxn];
  11. int n,m,ans,num;
  12. void init()
  13. {
  14. memset(deg,0,sizeof(deg));
  15. memset(cost,0,sizeof(cost));
  16. for(int i=0;i<maxn;i++) G[i].clear();
  17. for(int i=0;i<maxn;i++) cost[i]=888;
  18. }
  19. void bfstop()
  20. {
  21. for(int i=1;i<=n;i++)
  22. {
  23. if(deg[i]==0)
  24. hyx.push(i);
  25. }
  26. while(!hyx.empty())
  27. {
  28. int p=hyx.front();
  29. ans+=cost[p];
  30. num++;
  31. hyx.pop();
  32. for(int i=0;i<G[p].size();i++)
  33. {
  34. --deg[G[p][i]];
  35. if(deg[G[p][i]]==0)
  36. {
  37. cost[G[p][i]]=cost[p]+1;
  38. hyx.push(G[p][i]);
  39. }
  40. }
  41. }
  42. }
  43. int main()
  44. {
  45. int a,b;
  46. while(cin>>n>>m)
  47. {
  48. init();
  49. ans=0;
  50. num=0;
  51. for(int i=0;i<m;i++)
  52. {
  53. cin>>a>>b;
  54. G[b].push_back(a);
  55. deg[a]++;
  56. }
  57. bfstop();
  58. if(num!=n) cout<<"-1"<<endl;
  59. else cout<<ans<<endl;
  60. }
  61. return 0;
  62. }

D - 欧拉回路 HDU - 1878

裸的判断是否存在欧拉回路模板,回路的话没有奇数个数的点,欧拉路的话至多2个奇数的点,作为起点和终点。这里无向图,记录每个点的度数,并查集再判断图是否连通,满足欧拉路。

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <algorithm>
  4. #include <cstring>
  5. const int maxn=5e4+5;
  6. using namespace std;
  7. int deg[maxn],par[maxn];
  8. int n,m;
  9. int find(int x)
  10. {
  11. if(x==par[x])
  12. return x;
  13. else
  14. return par[x]=find(par[x]);
  15. }
  16. void unite(int x,int y)
  17. {
  18. x=find(x);
  19. y=find(y);
  20. if(x!=y)
  21. par[x]=y;
  22. }
  23. void init(){
  24. for(int i=1;i<=n;++i)
  25. par[i]=i;
  26. memset(deg,0,sizeof(deg));
  27. }
  28. int main()
  29. {
  30. while(cin>>n>>m)
  31. {
  32. int a,b,cnt=0,gen=0;
  33. init();
  34. for(int i=1;i<=m;++i)
  35. {
  36. scanf("%d%d",&a,&b);
  37. if(a==b) continue;
  38. else
  39. {
  40. deg[a]++;
  41. deg[b]++;
  42. unite(a,b);
  43. }
  44. }
  45. for(int i=1;i<=n;i++)
  46. {
  47. if(deg[i]&1)
  48. cnt++;
  49. if(par[i]==i)
  50. gen++;
  51. }
  52. if(cnt==0&&gen==1)
  53. printf("1\n");
  54. else
  55. printf("0\n");
  56. }
  57. return 0;
  58. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注