标签:10 NOIP int void namespace 多校 col 补图 联考
题意
对于给定的图,要求将其分为两张完全图。对于一种分法,其值为两张完全图边数之和。求所有分法最小值。
思路
建立原图的补图,显然这张图上相连的都是原来不能呆在同一组里的。对于补图中的每一个联通块都进行染色。
如果有两个节点在补图上相连且颜色一样,显然输出-1。
如果他们不相连但是颜色一样,那么必须放在同一组里。(如果不放在同一组里,就会出现一个与它们颜色不同的节点无处可放)
维护一个bool数组\(f[i]\)表示i人一组可不可行,统计每种颜色的数量,进行转移即可。
代码
#include <bits/stdc++.h>
using namespace std;
namespace StandardIO {
template<typename T>inline void read (T &x) {
x=0;T f=1;char c=getchar();
for (; c<'0'||c>'9'; c=getchar()) if (c=='-') f=-1;
for (; c>='0'&&c<='9'; c=getchar()) x=x*10+c-'0';
x*=f;
}
template<typename T>inline void write (T x) {
if (x<0) putchar('-'),x*=-1;
if (x>=10) write(x/10);
putchar(x%10+'0');
}
}
using namespace StandardIO;
namespace Project {
const int N=701;
const int INF=2147483647;
int n,m,ans=INF;
int G[N][N],color[N],size[2],f[N],t[N];
void dfs (int now,int col) {
color[now]=col,++size[col==1];
for (register int i=1; i<=n; ++i) {
if (i==now||G[now][i]) continue;
if (!color[i]) dfs(i,-col);
else if (color[i]==col) {
write(-1);
exit(0);
}
}
}
inline void MAIN () {
read(n),read(m);
for (register int i=1,x,y; i<=m; ++i) {
read(x),read(y);
G[x][y]=G[y][x]=1;
}
f[0]=1;
for (register int i=1; i<=n; ++i) {
if (color[i]) continue;
size[0]=size[1]=0;
dfs(i,1);
memset(t,0,sizeof(t));
for (register int j=0; j<=n; ++j) {
t[j+size[0]]|=f[j];
t[j+size[1]]|=f[j];
}
for (register int j=0; j<=n; ++j) {
f[j]=t[j];
}
}
for (register int i=0; i<=n/2; ++i) {
if (f[i]||f[n-i]) ans=min(ans,i*(i-1)/2+(n-i)*(n-i-1)/2);
}
write(ans);
}
}
int main () {
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
Project::MAIN();
}
标签:10,NOIP,int,void,namespace,多校,col,补图,联考 来源: https://www.cnblogs.com/ilverene/p/11620107.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。