AGC035 B - Even Degrees【思维·树形结构的妙用】
一句话题意:
首先,每一条边会产生1个入度,1个出度,因此,如果边的数量是奇数的话,图的所有节点的总出度就是奇数,不可能每个节点的出度都是偶数,因此无解。
有解时,我们先找出原图中的一棵生成树,然后非树边可以随便定方向。
接下来从儿子到父亲遍历这棵树。
对于每个点,我们先处理完所有子节点,然后只考虑这个点与父节点之间边的方向。
如果当前节点出度为奇数,边的方向就是向父亲,否则,边的方向就是向当前节点。
这样我们可以保证除根节点外所有节点出度都是偶数。而总边数是偶数,所以根节点出度也是偶数。
因为奇偶是只需要留一条边来就可以保证的,那么需要确定一个合适的顺序,不会产生矛盾(不知道怎么说,大概就是有时候在图中$dp$需要拓扑排序那种感觉,要确定一个合适的递推顺序)。树就是一种符合这种条件的数据结构。
上代码:(代码里面有个注释掉的东西,应该是可以那么写的,但是想了想写生成树还是按边来我最顺手,毕竟考试的时候求稳)
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #include<vector> 5 using namespace std; 6 #define N 100005 7 #define M 100005 8 struct node{ 9 int u,v; 10 }edge[M],ans[M]; 11 int n,m,cnt; 12 vector<int>G[N],T[N]; 13 bool vis[M]; 14 //bool vis[N]; 15 int d[N],ft[N]; 16 int rt=-1; 17 /*void dfs(int u,int f) 18 { 19 vis[u]=1; 20 for(int i=0;i<G[u].size();i++) 21 { 22 int v=G[u][i]; 23 if(vis[v]||v==f) continue; 24 T[u].push_back(v); 25 T[v].push_back(u); 26 dfs(v,u); 27 } 28 }*/ 29 int Find(int x) 30 { 31 if(ft[x]==x) 32 return x; 33 return ft[x]=Find(ft[x]); 34 } 35 bool Union(int x,int y) 36 { 37 int u=Find(x),v=Find(y); 38 if(u==v) return 0; 39 if(u>v) ft[u]=v; 40 else ft[v]=u; 41 return 1; 42 } 43 void dfs2(int u,int f) 44 { 45 //printf("%d\n",u); 46 for(int i=0;i<T[u].size();i++) 47 { 48 int v=T[u][i]; 49 if(v==f) continue; 50 dfs2(v,u); 51 } 52 if(u==rt) return ; 53 if(d[u]&1) ans[++cnt].u=u,ans[cnt].v=f,d[u]++; 54 else ans[++cnt].u=f,ans[cnt].v=u,d[f]++; 55 //printf("%d %d %d %d\n",u,d[u],ans[cnt].u,ans[cnt].v); 56 } 57 void Init() 58 { 59 for(int i=1;i<=n;i++) 60 ft[i]=i; 61 int tot=0; 62 for(int i=1;i<=m;i++) 63 { 64 if(Union(edge[i].u,edge[i].v)) 65 { 66 T[edge[i].u].push_back(edge[i].v); 67 T[edge[i].v].push_back(edge[i].u); 68 if(rt==-1) rt=edge[i].u; 69 vis[i]=1; 70 tot++; 71 } 72 if(tot==n-1) break; 73 } 74 cnt=0; 75 for(int i=1;i<=m;i++) 76 if(!vis[i]) 77 { 78 ans[++cnt].u=edge[i].u,ans[cnt].v=edge[i].v; 79 d[edge[i].u]++; 80 //printf("**%d %d\n",edge[i].u,edge[i].v); 81 } 82 dfs2(rt,-1); 83 } 84 int main() 85 { 86 //freopen("degree.in","r",stdin); 87 //freopen("degree.out","w",stdout); 88 scanf("%d %d",&n,&m); 89 if(m&1) 90 { 91 puts("-1"); 92 return 0; 93 } 94 for(int i=1;i<=m;i++) 95 { 96 int u,v;scanf("%d %d",&u,&v); 97 G[u].push_back(v); 98 G[v].push_back(v); 99 edge[++cnt].u=u,edge[cnt].v=v; 100 } 101 //dfs(1);//Find ST 102 Init();//Find ST 103 for(int i=1;i<=cnt;i++) 104 printf("%d %d\n",ans[i].u,ans[i].v); 105 return 0; 106 }
转载请注明出处,有疑问欢迎探讨
博主邮箱 2775182058@qq.com