把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

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 }
Code

 

 

posted @ 2019-11-04 20:42  Starlight_Glimmer  阅读(282)  评论(0编辑  收藏  举报
浏览器标题切换
浏览器标题切换end