D. Complete Mirror(待填的坑)

题目链接:

https://codeforces.com/contest/1182/problem/D

题目大意:

让你找到一个点,使得剩下的所有点满足   任意两个点v1,v2.;如果dis(v1,rt)==dis(v2,rt),则连向v1的边的个数等于连向v2的边的个数。

具体思路:

思路一:

先找到树的重心,然后从这个重心开始,找一条单链(这条链上的节点度都为2),然后这条链上最远的点和最近的点;只需要检验这三个点就可以了。

思路二:

通过对树进行一个拓扑序,找到第n次找到的点(有点对称的感觉)。然后剩下的就是和思路一后半段相同了。

ps:我也不知道咋证明,,画了好多图都是符合的,等以后有机会补上证明把(咕咕咕)

AC代码::

  1 #include<iostream>
  2 #include<cmath>
  3 #include<stack>
  4 #include<stdio.h>
  5 #include<algorithm>
  6 #include<queue>
  7 #include<vector>
  8 #include<cstring>
  9 using namespace std;
 10 # define inf 0x3f3f3f3f
 11 # define ll long long
 12 const int maxn = 2e5+100;
 13 vector<int>Edge[maxn];
 14 int in[maxn],degree[maxn];
 15 int n;
 16 int topu()
 17 {
 18     queue<int>q;
 19     int num=0;
 20     for(int i=1; i<=n; i++)
 21     {
 22         if(in[i]==1)
 23         {
 24             num++;
 25             q.push(i);
 26         }
 27     }
 28     int rt=0;
 29     while(!q.empty())
 30     {
 31         int top=q.front();
 32         q.pop();
 33         for(int i=0; i<Edge[top].size(); i++)
 34         {
 35             int to=Edge[top][i];
 36             if(in[to]==1)continue;;
 37             if(--in[to]==1)
 38             {
 39                 q.push(to);
 40                 if(++num==n)
 41                     rt=to;
 42             }
 43         }
 44     }
 45     return rt;
 46 }
 47 int dis[maxn];
 48 int deg[maxn];
 49 bool judge(int rt)
 50 {
 51     memset(dis,0,sizeof(dis));
 52     memset(deg,0,sizeof(deg));
 53     dis[rt]=1;
 54     queue<int>q;
 55     q.push(rt);
 56     while(!q.empty())
 57     {
 58         int top=q.front();
 59         q.pop();
 60         for(int i=0; i<Edge[top].size(); i++){
 61             int to=Edge[top][i];
 62             if(!dis[to])
 63             q.push(to);
 64             if(!dis[to])
 65             {
 66                 dis[to]=dis[top]+1;
 67             }
 68             if(!deg[dis[to]])
 69                 deg[dis[to]]=degree[to];
 70             if(deg[dis[to]]!=degree[to])
 71                 return false;
 72         }
 73     }
 74     return true;
 75 }
 76 int len[maxn];
 77 void dfs(int v,int rt,int dep)
 78 {
 79     if(degree[v]>2)
 80         return ;
 81     if(degree[v]==1){
 82     len[v]=dep;
 83     return ;
 84     }
 85     for(int i=0; i<Edge[v].size(); i++)
 86     {
 87         int to=Edge[v][i];
 88         if(to==rt)
 89             continue;
 90         dfs(to,v,dep+1);
 91     }
 92 }
 93 int main()
 94 {
 95     int st,ed;
 96     scanf("%d",&n);
 97     if(n==1){
 98     printf("1\n");
 99     return 0;
100     }
101     for(int i=1; i<n; i++)
102     {
103         scanf("%d %d",&st,&ed);
104         Edge[st].push_back(ed);
105         Edge[ed].push_back(st);
106         in[st]++,in[ed]++;
107         degree[st]++,degree[ed]++;
108     }
109     int rt=topu();
110     if(judge(rt))
111     {
112         printf("%d\n",rt);
113         //cout<<rt<<endl;
114         return 0;
115     }
116     for(int i=0; i<Edge[rt].size(); i++)
117     {
118         int to=Edge[rt][i];
119         dfs(to,rt,1);
120     }
121     int mx=0,id=-1;
122     for(int i=1; i<=n; i++)
123     {
124         if(len[i]&&len[i]>mx)
125         {
126             mx=len[i];
127             id=i;
128         }
129     }
130     if(id!=-1)
131     {
132         if(judge(id))
133         {
134             printf("%d\n",id);
135             return 0;
136         }
137     }
138     int minx=inf ;
139     id=-1;
140     for(int i=1; i<=n; i++)
141     {
142         if(len[i]&&len[i]<minx)
143         {
144             minx=len[i];
145             id=i;
146         }
147     }
148     if(id!=-1)
149     {
150         if(judge(id))
151         {
152             printf("%d\n",id);
153             return 0;
154         }
155     }
156     printf("-1\n");
157     return 0;
158 }

 

转载于:https://www.cnblogs.com/letlifestop/p/11019093.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值