C. Team-Building

目录

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

#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 pii;
typedef pair pll;

template  bool chkmax(T &x,T y){return x 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 sc[500005];
vector 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 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。

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

你可能感兴趣的:(CodeForces,算法,c++,数据结构)