标签: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