标签:mit lse nim node frame osi include cep over
#include<bits/stdc++.h> #define N 100005 using namespace std; struct Edge{ int to,next; bool able; }edge[N*4];///要多于总边数的4倍 (*2双向边 并且可能加边) int n,m, Degree[N],///每个点的度 Head[N], ///每个点的最后一条加入的边的序号 cnt, ///边的序号 res; ///一共找到的路径 bool vis[N]; vector<int>st;///保存一个连通块中度为奇数的点 vector<int>road[N]; void add(int u,int v){ edge[++cnt].next = Head[u]; edge[cnt].to = v; edge[cnt].able = true; Head[u] = cnt; ++Degree[u]; } inline void add_edge(int u,int v){ add(u,v); add(v,u); } void dfs(int s){ vis[s] = true; if(Degree[s]&1)st.push_back(s); for(int i = Head[s] ; i ; i = edge[i].next){ if(!vis[edge[i].to])dfs(edge[i].to); } } void dfs2(int s){ for(int i = Head[s] ; i ; i = edge[i].next){ if(edge[i].able) { edge[i].able = edge[i ^ 1].able = false; dfs2(edge[i].to); if(i>2*m+1)++res;///说明此边是由奇数度点添加得到的,所以这条回路已经结束 else { road[res].push_back(i/2*(2*(i&1)-1)); } } } } int main(){ int u,v; while (cin>>n>>m){ cnt = 1,res = 0; for(int i = 0 ; i < m ; ++i){ scanf("%d %d",&u,&v); add_edge(u,v); } for(int i = 1 ; i <= n ; ++i){ if(!vis[i] and Degree[i]) { dfs(i);///找到连通块和奇数度的点 if (st.empty()) { st.push_back(i); st.push_back(i); } for (int j = 2; j < st.size(); j += 2) {///为从第二对开始的奇数度的点添加一条双向边 add_edge(st[j], st[j + 1]); } res++; dfs2(st[0]); st.clear(); } } printf("%d\n",res); for(int i = 1 ; i <= res ; ++i){ printf("%d",road[i].size()); for(int j = 0 ; j < road[i].size() ; ++j){ printf(" %d",road[i][j]); } puts(""); road[i].clear(); } for(int i = 1 ; i <= n ; ++i){ vis[i] = false; Head[i] = 0; Degree[i] = 0; } } }
Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 440 Accepted Submission(s): 65
Special Judge
Solution:
在每一个联通块内考虑,设联通块内,一张连通图需要n笔画完则有 n = max ( |degree(奇数)| / 2 , 1)
如果有两个奇度顶点,其他的都为偶数,那么也可以选择任意的一个奇度顶点来跑欧拉路径。但是如果一个联通块的奇度顶点大于2,那么就需要对奇度顶点之间进行连边,然后选择一个奇度顶点跑欧拉路径,然后最后将多连的边删去就好了
Code:
标签:mit lse nim node frame osi include cep over
原文地址:https://www.cnblogs.com/zhangbuang/p/11700769.html