C. Team-Building

代码实现了一个算法,用于在给定的学术团体中分配学生,使得没有朋友在同一团队,计算最多可以组建的满足条件的游戏团队数量。涉及图的染色和并查集操作。
摘要由CSDN通过智能技术生成

目录

1.Problem

2.Input

3.Output

4.Examples

4.1input

4.2output

5.Code

6.Conclusion


1.Problem

The new academic year has started, and Berland's university has nn first-year students. They are divided into kk academic groups, however, some of the groups might be empty. Among the students, there are mm pairs of acquaintances, and each acquaintance pair might be both in a common group or be in two different groups.

Alice is the curator of the first years, she wants to host an entertaining game to make everyone know each other. To do that, she will select two different academic groups and then divide the students of those groups into two teams. The game requires that there are no acquaintance pairs inside each of the teams.

Alice wonders how many pairs of groups she can select, such that it'll be possible to play a game after that. All students of the two selected groups must take part in the game.

Please note, that the teams Alice will form for the game don't need to coincide with groups the students learn in. Moreover, teams may have different sizes (or even be empty).

2.Input

3.Output

4.Examples

4.1input

6 8 3
1 1 2 2 3 3
1 3
1 5
1 6
2 5
2 6
3 4
3 5
5 6

4.2output

2

5.Code

#include<bits/stdc++.h>

#define pb push_back
#define mp make_pair
#define fi first
#define se second

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;

template <typename T> bool chkmax(T &x,T y){return x<y?x=y,true:false;}
template <typename T> bool chkmin(T &x,T y){return x>y?x=y,true:false;}

int readint(){
	int x=0,f=1; char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}

int n,m,k,tot,scnt,timer1,timer2; ll ans;
int v[1000005],nxt[1000005],h[500005],col[500005],bel[500005],mark1[500005],mark2[500005];
int c[500005],lab[500005],rg[500005],rt[500005],f[500005],siz[500005],hv[500005];
bool vis[500005],can[500005];
vector<int> sc[500005];
vector<pii> sh[2],nd[500005];

int getf(int x){return x==f[x]?x:f[x]=getf(f[x]);}

void merge(int x,int y){
	int fx=getf(x),fy=getf(y);
	if(fx==fy) return;
	f[fx]=fy,siz[fy]+=siz[fx];
}

void addedge(int x,int y){
	v[++tot]=y; nxt[tot]=h[x]; h[x]=tot;
	v[++tot]=x; nxt[tot]=h[y]; h[y]=tot;
}

bool dfs1(int u){
	bel[u]=scnt;
	for(int p=h[u];p;p=nxt[p]){
		if(c[v[p]]!=c[u]) continue;
		if(vis[v[p]]){
			if(col[v[p]]!=(col[u]^1)) return false;
			continue;
		}
		vis[v[p]]=1,col[v[p]]=col[u]^1;
		if(!dfs1(v[p])) return false;
	}
	return true;
}

void dfs2(int u){
	for(int p=h[u];p;p=nxt[p]){
		if(c[v[p]]!=c[u]){
			if(can[c[v[p]]]) continue;
			if(mark1[bel[v[p]]]!=timer1) mark1[bel[v[p]]]=timer1,lab[bel[v[p]]]=-1;
			if(mark2[c[v[p]]]!=timer2) mark2[c[v[p]]]=timer2,rg[c[v[p]]]=0;
			if(lab[bel[v[p]]]==-1){
				lab[bel[v[p]]]=col[v[p]]^col[u];
				sh[lab[bel[v[p]]]].pb(mp(c[v[p]],bel[v[p]]));
			}
			else if(lab[bel[v[p]]]!=(col[v[p]]^col[u])){
				if(rg[c[v[p]]]==0) ans--,rg[c[v[p]]]=1;
				else;
			}
			continue;
		}
		if(vis[v[p]]) continue;
		vis[v[p]]=1;
		dfs2(v[p]);
	}
}

int main(){
	n=readint(); m=readint(); k=readint();
	for(int i=1;i<=n;i++) c[i]=readint();
	for(int i=1;i<=m;i++) addedge(readint(),readint());
	for(int i=1;i<=n;i++){
		if(!vis[i]){
			vis[i]=1,scnt++,rt[scnt]=i,col[i]=0;
			if(!dfs1(i)) can[c[i]]=1;
			sc[c[i]].pb(scnt);
		}
	}
	int ccnt=0;
	for(int i=1;i<=n;i++) if(can[i]) ccnt++;
	for(int i=1;i<=n;i++) vis[i]=0;
	for(int i=1;i<=scnt;i++) f[i]=i,siz[i]=1;
	for(int i=1;i<=k;i++){
		if(can[i]) continue;
		ans+=k-1-ccnt,timer2++;
		vector<int> gar(0);
		for(auto r:sc[i]){
			timer1++,sh[0].clear(),sh[1].clear();
			dfs2(rt[r]);
			sort(sh[0].begin(),sh[0].end());
			sort(sh[1].begin(),sh[1].end());
			for(int j=0;j<(int)sh[0].size()-1;j++) if(sh[0][j].fi==sh[0][j+1].fi&&rg[sh[0][j].fi]==0) merge(sh[0][j].se,sh[0][j+1].se);
			for(int j=0;j<(int)sh[1].size()-1;j++) if(sh[1][j].fi==sh[1][j+1].fi&&rg[sh[1][j].fi]==0) merge(sh[1][j].se,sh[1][j+1].se);
			for(auto g:sh[0]) if(rg[g.fi]==0) gar.pb(g.se),hv[g.fi]=g.se;
			for(auto g:sh[1]){
				if(rg[g.fi]==0){
					gar.pb(g.se);
					if(hv[g.fi]) nd[g.fi].pb(mp(g.se,hv[g.fi])),hv[g.fi]=0;
				}
			}
			for(auto g:sh[0]) hv[g.fi]=0;
		}
		for(auto r:gar){
			if(rg[c[rt[r]]]==0){
				for(auto g:nd[c[rt[r]]]){
					if(getf(g.fi)==getf(g.se)){
						ans--;
						break;
					}
				}
			}
			nd[c[rt[r]]].clear();
		}
		for(auto r:gar) f[r]=r,siz[r]=1;
		gar.clear();
	}
	printf("%lld\n",ans/2);
	return 0;
}

6.Conclusion

这段C++代码实现了一个图论算法,其主要功能是计算一种图的性质,并输出相应的结果。以下是对代码的简要总结:

1.输入:

        通过 readint 函数读取整数。
        读取图的节点数 n,边数 m,以及参数 k。
        读取每个节点的颜色 c[i]。
        读取图的边信息,构建邻接表。

2.图的处理:

        将节点按照颜色分组,并检测是否存在染色冲突。
        通过深度优先搜索(DFS)处理每个组内的节点,构建新的数据结构用于后续处理。

3.处理过程:

        对于每种颜色,执行一系列操作来计算图的性质。
        使用并查集数据结构来合并节点。
        对每个节点的邻居进行遍历,检测是否存在一定条件下的合并。
        根据一些规则更新计数值 ans。

4.输出:

        输出最终计算得到的结果 ans 除以 2。

        总体而言,该代码通过图的处理和一些规则判断来计算图的某些性质,并输出相应的结果。具体的性质和规则需要进一步深入了解代码的逻辑和背景。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

向阳而生__

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值