CodeForces 550D Regular Bridge(构造)
【题目链接】click here~~
【题目大意】
给出一个k,表示一个无向图的每一个节点的度数为k,而且在无向图中有一条边假设去掉之后会把这个无向图分成两个部分,要求输出这个图
【解题思路】
这里參考了文章的思路。讲的比較清楚,详细点击:click here~~
首先。我们能够确定。这个图能够分为两个对称的部分,而这两个对称的部分就是以一条边来连接的,这条边就是题目中要求的桥
确定了对称的特性之后。我们仅仅须要着力讨论一边的状况就可以
如果连接这条桥的节点为n。那么n节点就仅仅剩下k-1的边能够分配。也就是对于这一边我们最少还须要k-1个节点。那么我们先放置k-1个节点,并且使得它们都与n相连,那么n如今的度为k。可是如今这k-1个节点的度数都仅仅有1。并且如果这k-1个节点的话,是无法使得它们的度数都为k的
那么怎么办呢?证明我们还须要添加节点才行,那么添加几个呢?添加一个是不行的,由于仅仅添加1个节点的话,我们是无法使得这个新添加的节点达到K的度的。那么两个呢?
我们能够发现,添加两个刚刚好,首先我们令新添加的两个节点编号为n-1,n-2,首先使得它们互相相连。那么他们正好都仅仅剩下k-1个度了,正好能够与之前的k-1个节点相连
在相连之后。我们能够发现之前k-1个节点,编号为n-3~1。如今都仅仅剩下k-3个度了。那么问题就攻克了,对于这些节点。我们仅仅须要奇偶来考虑。就能够使得它们都满足k个度的要求,那么问题就攻克了。图形例如以下
并且我们要注意,偶数的度是不可行的,由于偶数的度的情况下。编号为2的度是处理不了的
代码:
<span style="font-size:14px;">#include <bits/stdc++.h> using namespace std; const int N=5*1e2; int num[N]; bool mat[N][N];///邻接矩阵 bool vis[N][N]; vector <int >G[N];///邻接表 int k,n,m,l,r,q,ans,cnt,top; typedef long long LL; typedef unsigned long long LLU; typedef pair<int,int>pii; void add(int from,int to) { G[from].push_back(to); G[to].push_back(from); } void init() { memset(mat,0,sizeof(mat)); memset(vis,false,sizeof(vis)); } int main() { while(scanf("%d",&n)!=EOF) { init(); if(n%2==0) { puts("NO"); continue; } if(n==1) { puts("YES"); puts("2 1"); puts("1 2"); } else { for(int i=2; i<=n; ++i)///从1出衍生出点(2, 3, …, k) { mat[i][1]=mat[1][i]=1; } for(int i=2; i<=n; ++i)///从2出衍生出点(k + 1, k + 2, …, 2 * k - 1) { for(int j=n+1; j<=2*n-1; ++j) mat[i][j]=mat[j][i]=1; } for(int i=n+1; i<=2*n-1; i+=2)///对于编号为(2, 3, …, k)的点。向编号为(k + 1, k + 2, …, 2 * k - 1)的点都连一条边 { mat[i][i+1]=mat[i+1][i]=1; } ans=0; for(int i=1; i<=2*n-1; ++i) { for(int j=1; j<=2*n-1; j++) ans+=mat[i][j]; } puts("YES"); printf("%d %d\n",4*n-2,++ans); for(int i=1; i<=2*n-1; ++i) { for(int j=1; j<=2*n-1; ++j) { if(mat[i][j]&&!vis[i][j]) { printf("%d %d\n",i,j); printf("%d %d\n",i+2*n-1,j+2*n-1); vis[i][j]=vis[j][i]=true; } } } printf("%d %d\n",1,2*n); } } return 0; }</span>