• 【数据结构】欧拉回路(优化最短路-图论)


    题面

    题意

    有一天一位灵魂画师画了一张图,现在要你找出欧拉回路,即在图中找一个环使得每条边都在环上出现恰好一次。

    一共两个子任务:

    1. 这张图是无向图。50( 分)
    2. 这张图是有向图。50( 分)

    输入格式

    第一行一个整数 t,表示子任务编号。t∈{1,2},如果 t=1 则表示处理无向图的情况,如果 t=2 则表示处理有向图的情况。

    第二行两个整数 n,m,表示图的结点数和边数。

    接下来 m 行中,第 i 行两个整数 vi,ui,表示第 i 条边(从 1 开始编号),保证 1 ≤ vi,ui ≤ n。

    如果 t=1 则表示 vi 到 ui 有一条无向边。

    如果 t=2 则表示 vi 到 ui 有一条有向边。

    图中可能有重边也可能有自环。

    输出格式

    如果不可以一笔画,输出一行 “NO”。

    否则,输出一行 “YES”,接下来一行输出一组方案。

    如果 t=1,输出 m 个整数 p1,p2,…,pm。令 e=∣pi∣,那么 e 表示经过的第 i 条边的编号。如果 pi 为正数表示从 ve 走到 ue,否则表示从 ue 走到 ve。
    如果 t=2,输出 m 个整数 p1,p2,…,pm。其中 pi 表示经过的第 i 条边的编号。

    样例数据

    1. 【样例输入1
    2. 1
    3. 3 3
    4. 1 2
    5. 2 3
    6. 1 3
    7. 【样例输出1
    8. YES
    9. 1 2 -3
    10. 【样例输入2
    11. 2
    12. 5 6
    13. 2 3
    14. 2 5
    15. 3 4
    16. 1 2
    17. 4 2
    18. 5 1
    19. 【样例输出】
    20. YES
    21. 4 1 3 5 2 6

    思路

    • 欧拉回路的模板,但只能算一个环,图原本可能不连通。 另外会有很多自环,也要优化一下,否则会超时。
    • 有向图的欧拉回路就是入度与出度之和一定是一个偶数(如果入度为1,出度为-1,和为0),无向图的点度一定是偶数,用这个来判断是否为欧拉回路。

    代码(70分)

    应该是没有优化很多自环的情况

    1. #include <bits/stdc++.h>
    2. #define ll long long
    3. #include <vector>
    4. #include <stack>
    5. #define db double
    6. #define ls p<<1
    7. #define rs p<<1|1
    8. using namespace std;
    9. const int N=100010, M=1000010;
    10. inline ll read() {
    11. char c=getchar(); int x=0,f=1;
    12. while(c>'9'||c<'0') {if(c=='-') f=-1;c=getchar();}
    13. while(c<='9'&&c>='0') {x=(x<<3)+(x<<1)+(c&15);c=getchar();}
    14. return x*f;
    15. }
    16. bool flag[M];
    17. ll in[N], out[N], f[M];
    18. int head[N], ver[M] ,nxt[M];
    19. ll type, n, m, tot=1, x, y;
    20. vector<ll> ans;
    21. void add(int u,int v) {
    22. ver[++tot]=v;
    23. nxt[tot]=head[u];
    24. head[u]=tot;
    25. }
    26. struct ed {
    27. int to,nxt;
    28. }t[10010<<1];
    29. void dfsearch(int x) {
    30. for(int &i=head[x],y; y=ver[i],i; i=nxt[i]) {
    31. ll c=(type==1?i/2:i-1);
    32. ll sig = i%2;
    33. if(flag[c]) continue;
    34. flag[c]=1;
    35. dfsearch(y);
    36. if(type==1)
    37. ans.push_back(sig?-c:c);
    38. else
    39. ans.push_back(c);
    40. }
    41. }
    42. int main () {
    43. type = read();
    44. n = read();
    45. m = read();
    46. for(int i=1; i<=m; i++) {
    47. x = read();
    48. y = read();
    49. add(x,y);
    50. if(type==1) add(y,x);
    51. out[x]++; in[y]++;
    52. }
    53. if(type==1) {
    54. for(int i=1; i<=n; i++)
    55. if((in[i]+out[i])%2) {
    56. printf("NO\n");
    57. return 0;
    58. }
    59. }
    60. else {
    61. for(int i=1; i<=n; i++)
    62. if(in[i]!=out[i]) {
    63. printf("NO\n");
    64. return 0;
    65. }
    66. }
    67. for(int i=1; i<=n; i++)
    68. if(head[i]) {
    69. dfsearch(i);
    70. break;
    71. }
    72. if(ans.size()!=m) {
    73. cout << "NO" << endl;
    74. return 0;
    75. }
    76. cout<<"YES"<<endl;
    77. if(type==1)
    78. for(int i=0; i<=m-1; i++)
    79. printf("%lld ", -1*ans[i]);
    80. if(type==2)
    81. for(int i=m-1; i>=0; i--)
    82. printf("%lld ", ans[i]);
    83. puts("");
    84. return 0;
    85. }

    AC_Code

    1. #pragma comment(linker, "/STACK:102400000,102400000")//手动开大栈区
    2. #include<bits/stdc++.h>
    3. using namespace std;
    4. int const N=4e5+10;
    5. int n,m,cnt,h[N],st[N<<1],top,in[N],out[N],vis[N<<1],f[N],us[N<<1],num[N];
    6. vector<int> a[N],c[N],b[N];
    7. void dfs(int x,int lm){
    8. while (b[x].size()){
    9. int y=b[x][b[x].size()-1];
    10. int t=c[x][b[x].size()-1];
    11. b[x].pop_back();
    12. c[x].pop_back();
    13. if(y<lm) continue;
    14. if(!vis[abs(y)]){
    15. vis[abs(y)]=1;
    16. dfs(t,lm);
    17. st[++top]=y;
    18. }
    19. }
    20. }
    21. int find(int x){
    22. return x==f[x]? x:f[x]=find(f[x]);
    23. }
    24. int main(){
    25. int t;
    26. scanf("%d",&t);
    27. cnt=top=0;
    28. memset(h,0,sizeof(h));
    29. memset(vis,0,sizeof(vis));
    30. memset(in,0,sizeof(in));
    31. memset(out,0,sizeof(out));
    32. for(int i=1;i<=n;i++)
    33. a[i].clear();
    34. scanf("%d%d",&n,&m);
    35. for(int i=1;i<=n;i++) f[i]=i;
    36. for(int i=1;i<=m;i++){
    37. int x,y;
    38. scanf("%d%d",&x,&y);
    39. c[x].push_back(y);
    40. c[y].push_back(x);
    41. b[x].push_back(i);
    42. b[y].push_back(-i);
    43. f[find(x)]=find(y);
    44. }
    45. for(int i=1;i<=n;i++)
    46. a[find(i)].push_back(i);
    47. int check=0,ot=0;
    48. for(int i=1;i<=n;i++)
    49. {
    50. if(a[i].size()==0) continue;
    51. int num=0,nd,sum=0;
    52. for(int j=0;j<a[i].size();j++){
    53. int x=a[i][j];
    54. nd=x;
    55. sum+=b[x].size();
    56. for(int k=0;k<c[x].size();k++){
    57. int v=c[x][k];
    58. int c=abs(b[x][k]);
    59. if(t==2 && b[x][k]<0) continue;
    60. if(us[c]) continue;
    61. us[c]=1;
    62. if(t==1) in[x]++,in[v]++;
    63. else out[x]++,in[v]++;
    64. }
    65. }
    66. for(int j=0;j<a[i].size();j++){
    67. int x=a[i][j];
    68. if(t==1){
    69. if(in[x]%2==1)
    70. num++;
    71. }else {
    72. if(in[x]!=out[x])
    73. num++;
    74. }
    75. }
    76. if(t==1){
    77. if(num==0)
    78. {
    79. if(sum)
    80. dfs(nd,-10000000),ot++;
    81. }
    82. else check=1;
    83. }else {
    84. if(num==0)
    85. {
    86. if(sum)
    87. dfs(nd,0),ot++;
    88. }
    89. else check=1;
    90. }
    91. }
    92. if(check || ot>1) printf("NO\n");
    93. else {
    94. printf("YES\n");
    95. for(int i=top;i>=1;i--) printf("%d ",st[i]);
    96. }
    97. return 0;
    98. }

  • 相关阅读:
    API安全
    高耗能工厂实现ESG能源管控的策略与实践-天拓四方
    理解3ds max 中的衰减贴图
    测试用例评审的旁观记录
    Flink 本地任务添加配置参数
    App自动化测试开元平台Appium-runner
    我要写整个中文互联网界最牛逼的JVM系列教程 | 「JVM与Java体系架构」章节:虚拟机与Java虚拟机介绍
    论文阅读:攻击者的《银河系漫游指南》:开展对互联网资源供应商的路径外攻击以劫持互联网资源 the Hijackers‘ Guide To The Galaxy
    数字孪生云渲染整体架构设计
    iview表格实现的编辑和expand功能
  • 原文地址:https://blog.csdn.net/Luoxiaobaia/article/details/124970499